1) Definición

La primera actividad de cualquier análisis y pronostico es definir el problema

En el libro Forecasting: Principles and Practice, capítulo primero, describe que es un pronóstico, que se puede pronosticar y cómo definir el problema, y algunos casos de estudios.

Lee más en el capítulo https://otexts.com/fpp3/determining-what-to-forecast.html

Descripción del las remesas

Es el envío de dinero de aquellas personas que radican en otra nación a su país de origen. Por ejemplo, los envíos de dinero que realizan los mexicanos que radican en Estados Unidos y Canadá a sus familias que viven en México.

Con el surgimiento de nuevas herramientas tecnológicas es más sencillo realizar esta transacción y el número de usuarios que la hacen se ha incrementado en los últimos años.

También existen las remesas enviadas por personas que se dedican a los negocios y tienen que pagar sueldos a los empleados contratados en el exterior, por ejemplo. Otra transferencia muy común es para estudiantes que no pueden trabajar y necesitan mantenerse en otro país mientras estudian.

Las remesas son la segunda fuente de divisas más importante de México después de los ingresos por petróleo. Representan cerca de 3% del PIB, 50% de las exportaciones petroleras, 135% de la inversión extranjera directa y 189% de los ingresos de viajeros internacionales.

Los ingresos por remesas provenientes del exterior ascendieron a 4,760 millones de dólares en diciembre de 2021, lo que implicó un aumento anual de 30.4%.

Por su parte, las remesas enviadas por residentes en México al exterior mostraron un crecimiento anual de 1.8%, al alcanzar un nivel de 114 millones de dólares.

Con estos resultados, el superávit de la cuenta de remesas de México con el resto del mundo fue de 4,646 millones de dólares, mayor al de 3,538 millones de dólares que se presentó en diciembre de 2020.

Con series desestacionalizadas, en el último mes de 2021 los ingresos y egresos por remesas exhibieron retrocesos mensuales de 1.9 y 2.3%, en igual orden. Así, en diciembre de 2021 el superávit de la cuenta de remesas se situó en 4,600 millones de dólares, que se compara con el de 4,687 millones de dólares que se observó en noviembre de 2021.

Para la totalidad de 2021, el valor de los ingresos por remesas fue de 51,594 millones de dólares, monto superior al de 40,605 millones de dólares reportado en 2020 y que significó una expansión anual de 27.1%.

Durante 2021, el 98.9% del total de los ingresos por remesas se realizó a través de transferencias electrónicas, al ubicarse en 51,045 millones de dólares. Por su parte, las remesas efectuadas en efectivo y especie2 y las money orders representaron el 0.7 y 0.4% del monto total, respectivamente, al registrar niveles de 333 y 216 millones de dólares, en el mismo orden.

Los egresos por remesas sumaron 1,057 millones de dólares en 2021, cifra mayor a la de 899 millones de dólares observada en 2020 y que implicó un incremento anual de 17.6%.

Con estos resultados, el saldo superavitario de la cuenta de remesas en 2021 fue de 50,537 millones de dólares, cifra superior a la de 39,706 millones de dólares reportada en 2020 y que representó un avance anual de 27.3%.

Datos

Banco de México registra las remesas como parte de la balanza de pagos y tiene registro mensual desde 1995.

Los datos de Banxico pueden ser descargados en el siguiente enlace

Determinar que pronosticar

Se analizara el ingreso total de remesas, como se muestra en la captura siguiente.

Por que es importante analizar y pronosticar en el contexto social

El flujo de remesas internacionales tiene un efecto importante sobre la actividad económica en algunas entidades que se localizan en las regiones centrales y el sur del país. Esto condujo a que el incremento observado en las remesas haya inducido en 2016 un mayor crecimiento económico en estas regiones.

En efecto, como resultado de los patrones de gasto de los hogares, dichas entidades tienden a ser más propensas a concentrar el impacto de las remesas en las actividades comerciales y los servicios. Adicionalmente, los flujos de remesas contribuyen a suavizar el ingreso de los hogares ante choques sobre la actividad económica, en particular en el sector agropecuario.

Las remesas son la segunda fuente de divisas más importante de México. En los últimos años las remesas han alcanzado máximos históricos, además, han obtenido mayor atención por las recientes investigaciones que señalan cómo cárteles del narco lavan dinero vía remesas.

2) Datos

Importar

En las siguientes celdas se muestan los pasos para importar los datos desde mi espacio de trabajo. Por que es un archivo en formato Excel, la librería usada es readxl.

Lee más en el notebook introductorio visto en clase: tidyverse, sección Data science workflow, paso 1 Import Data.

También en el libro R for Data Science capítulo 20.

library(readxl)

#raw_data = read_xlsx(path = "/Users/danielnuno/GitHub/time_series_s2024/Analisis/remesas banxico.xlsx", sheet = "Hoja1", col_names = FALSE)
raw_data = read_xlsx(path = "~/GitHub/time_series_s2024/Analisis/remesas/remesas banxico.xlsx", sheet = "Hoja1", col_names = FALSE)
New names:
head(raw_data, 20)

Eliminar filas

Los datos no inician hasta la fila 18. Usando dplyr::slice se pueden eliminan las primeras 18 filas.

Lee más en el notebook introductorio visto en clase: tidyverse, sección Data science workflow, paso 3 understand your data.

También en el libro R for Data Science capítulo 27.

#raw_data = raw_data[-(1:18), ]
data = dplyr::slice(raw_data, -(1:18))
head(data, 2)

Renombra las columnas

Las dimensiones están nombradas como …1 y …2, por lo tanto es conveniente renombrarlas sin espacios ni caracteres especiales.

colnames(data) = c('date', 'value')
head(data, 2)

Cambia el tipo de dato de las columnas

Las columnas son chr pero date tiene que ser una fecha mensual y value son millones de dólares. Utiliza lubridate para hacer la transformación de la fecha o R básico.

Lee más en el notebook introductorio visto en clase: tidyverse, sección Data science workflow, paso 3 understand your data: data transformation.

También en el libro R for Data Science capítulo 17.

Transforma el tipo texto cómo numérico

data$date = as.numeric(data$date)

Transforma el número a fecha utilizando el argumento origin

El número representa un día en la serie que inicia el primero de enero de 1990. Por lo tanto utilizamos el argumento origin que indica el inicio de la serie.

data$date = as.Date(data$date, origin = "1899-12-30")

Crea una secuencía explicita la periodicidad mensual

data$date = seq(from = min(data$date), to = max(data$date), by = "1 month")
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(tsibble)

Attaching package: ‘tsibble’

The following object is masked from ‘package:lubridate’:

    interval

The following objects are masked from ‘package:base’:

    intersect, setdiff, union
data$date = yearmonth(data$date)
head(data, 2)

Cambia el tipo de dato de la columna value

data$value = as.numeric(data$value)
head(data, 2)

Crea un tsibble

Usando tsibble::as_tsibble() asigna la fecha como index. En este caso key no es necesario pero decide si es importante para tu serie.

Lee más en el notebook introductorio visto en clase: tidyverse, sección Data science workflow, paso 2 Tidy Data. Y el ejemplo 1.

También la documentación tsibble y el libro Forecast: Principles and Practice capítulo 2.1

data = as_tsibble(data, index=date, regular=TRUE)
head(data, 2)
interval(data)
<interval[1]>
[1] 1M

Valores faltantes y factores

Identifica si tu serie de tiempo tiene valores faltantes o factores y has las transformaciones correspondientes con ayuda del libro R for data science - Transform.

3) Análisis

Visualización de la serie

Utiliza ggplot2 para gráficar la serie

Lee más en el notebook introductorio visto en clase: tidyverse, sección Data science workflow, paso 3 Understand your data - visualization.

Ve los ejemplos y explicaciones vistas en clase: ggplot2, sección Gráficas con ggplot2.

También el libro Forecast: Principles and Practice capítulo 2.2

Time plot

library(ggplot2)
library(feasts)
Loading required package: fabletools
feasts::autoplot(data) + ggtitle('Remesas por mes') + ylab('Millones de dólares') + xlab('Fecha')
Plot variable not specified, automatically selected `.vars = value`

Patrones

Gráficamente presenta tendencia, estacionalidad y heteroscedasticidad. Parece presentar ciclos relacionados a la actividad económica.

Consulta el libro Forecast: Principles and Practice capítulo 2.3

Gráfica estacionales

Una gráfica estacional es lo mismo que un time plot pero graficada usando los periodos estacionales. En este caso la estacionalidad es mensual.

Consulta el libro Forecast: Principles and Practice capítulo 2.4

data %>% gg_season(value, labels = "both") +
    ggtitle('Remesas por año') + ylab('Millones de dólares') + xlab('Mes')

Utiliza plotly::ggplotly() hacer gráficos interactivos

suppressWarnings(library(plotly))
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
yearly_data_plot = data %>% gg_season(value, labels = "both") +
    ggtitle('Remesas por año') + ylab('Millones de dólares') + xlab('Mes')

ggplotly(yearly_data_plot)

Sub gráficas estacionales

Un gráfico alternativo que enfatiza los patrones estacionales es aquel en el que los datos de cada temporada se recopilan en minigráficos de tiempo separados.

Consulta el libro Forecast: Principles and Practice capítulo 2.5

subseries_plot = data %>% gg_subseries(value)
ggplotly(subseries_plot)

Gráfico de rezagos

Estos gráficos son gráficos de dispersión evaluados en los rezagos de la misma serie que miden la correlación entre periodos. En otras palabras, para esta serie de tiempo mensual, mide la relación de un mes en el tiempo contra un mes (n lags) del pasado.

Consulta el libro Forecast: Principles and Practice capítulo 2.7

lags_plots = data %>% filter(year(date) > 2018) %>% gg_lag(value, geom = "point", lags = 1:12) + labs(x = "lag(Remesa, k)")

suppressWarnings(ggplotly(lags_plots))

Autocorrelación

Así como la correlación mide el alcance de una relación lineal entre dos variables, la autocorrelación mide la relación lineal entre valores rezagados de una serie temporal.

Consulta el libro Forecast: Principles and Practice capítulo 2.8

data %>% ACF(value, lag_max = 12)
data %>% ACF(value, lag_max = 24) %>% autoplot() + labs(title='Remesas por año')

Cuando los datos tienen tendencia, las autocorrelaciones para desfases pequeños tienden a ser grandes y positivas porque las observaciones cercanas en el tiempo también lo son en valor. Por lo tanto, el ACF de una serie temporal con tendencia tiende a tener valores positivos que disminuyen lentamente a medida que aumentan los rezagos.

Cuando los datos son estacionales, las autocorrelaciones serán mayores para los rezagos estacionales (en múltiplos del período estacional) que para otros rezagos.

Sera importante realizar las mismas gráficas una vez que la serie sea estacional.

Además de lo descrito en la primera parte del documento, con las gráficas podemos observar lo siguiente:

Gráficamente presenta tendencia, estacionalidad. Parece presentar ciclos relacionados a la actividad económica.

es interesante observar con este gráfico que a partir del año 2004 los datos se ven separados, es decir, la amplitud de los datos se vuelve más grande en cada año después que pasa. Podemos concluir tres cosas con esto:

  • Los primeros siete u ocho años de la serie hay crecimiento, pero a partir del 2003 el crecimiento es exponencial de cómo era antes.
  • En esas fechas se volvió más fácil hacer transferencias electrónicas y por lo tanto contabilizarlo en la balanza de pagos.
  • El crecimiento puede ser también por la solidaridad de los migrantes.

En el 2001, en respuesta a la “Sociedad para la prosperidad” entre México y Estados Unidos, el Banco de México y los Bancos de la Reserva Federal de los Estados Unidos acordaron estudiar la posibilidad de interconectar sus sistemas de pagos. La interconexión ha provisto a nuestras economías de un mecanismo eficiente para intercambiar pagos entre cuentas bancarias de ambos países.

En octubre de 2003, los Bancos de la Reserva Federal de los Estados Unidos y el Banco de México conectaron sus sistemas de pago para el envío de los pagos de los pensionados del Gobierno de los Estados Unidos que radican en México.

Posteriormente, desde el 2 de febrero de 2004, los usuarios de las instituciones financieras de los Estados Unidos suscritas a Directo a México pueden enviar pagos a cualquier cuenta bancaria en México.

Desde julio de 2005, este servicio de pagos se registró con el nombre Directo a México

Entonces para considerar como periodos que han afectado la serie de tiempo tenemos:

  • 2003-10 facilidad de transferencias electrónicas
  • 2007-12, 2009-06 recesión global por crisis hipotecaria
  • 2020-02, 2020-04 recesión global por COVID-19
  • Apartir del 2018 hay un cambio de tendencia y el crecimieto es acelerado.

Con los gráficos de rezagos podemos apreciar que muestra mayor correlación con el periodo inmediato anterior (1) y el mismo periodo del año pasado (12). Es decir, se espera que se envié una similar cantidad de dinero comparada a estos dos periodos del pasado (1 y 12), pero para el periodo 12 se espera que se envié más dinero.

Estadística descriptiva

Medidas de tendencia central

Calcula la media, moda y mediana. Estos estadisticos pueden ser de la totalidad de la serie o por año o por periodo estacional.

print(paste('fecha inicial', min(data$date)))
[1] "fecha inicial 1995 Jan"
print(paste('fecha final', max(data$date)))
[1] "fecha final 2023 Dec"
print(paste('observaciones', nrow(data)))
[1] "observaciones 348"
print(paste('existen', sum(is.na(data)), 'datos faltantes'))
[1] "existen 0 datos faltantes"
summary(data[, 'value'])
     value       
 Min.   : 248.1  
 1st Qu.: 797.8  
 Median :1933.9  
 Mean   :1993.3  
 3rd Qu.:2453.4  
 Max.   :5817.8  

Observamos que, por mes, el promedio de millones de dólares es de $1,993.2 millones de dólares, el mínimo fue de $248.1 millones de dólares, mientras que el máximo fue de $5,817.8 millones.

boxplot = data %>% 
            mutate(year = year(date)) %>% 
            ggplot(aes(x = as.factor(year), y = value)) + 
            geom_boxplot() + 
            xlab('Año') + 
            ylab('Remesas')

ggplotly(boxplot)

Medidas de dispersión

Estos estadísticos que nos dan información al respecto de la variabilidad o separación de los datos generalmente respecto a la media. Nos ayudan a comprender la distribución de los datos y evitan tomar conclusiones erróneas al comparar distintos grupos.

sd(data$value)
[1] 1313.988
var(data$value)
[1] 1726565
library(EnvStats)
kurtosis(data$value)
[1] 0.5642417
skewness(data$value)
[1] 0.9010978
shapiro.test(data$value)

    Shapiro-Wilk normality test

data:  data$value
W = 0.91084, p-value = 1.773e-13
library(ggExtra)
p <- ggplot(data, aes(x=date, y=value)) + 
        geom_hline(yintercept =1000) + 
        geom_hline(yintercept =3000) +
        geom_point() + 
        ggtitle('Remesas por mes') + ylab('Millones de dólares') + xlab('Fecha')

ggMarginal(p, type='histogram', margins = 'y')

histogram = ggplot(data, aes(x = value)) +
  geom_histogram( bins = 20, fill = "black", color = "black", alpha = 0.5) +
  labs(title = "Histograma",
       x = "Value",
       y = "Densidad")

ggplotly(histogram)

La distribución presenta un sesgo de simetría negativo a la izquierda y aunque los valores no son tan grandes, alguna transformación sería útil antes de hacer la descomposición de la serie y los pronósticos.

Valores atípicos

La detección de outliers es importante para afinar nuestro pronóstico y eliminar las observaciones atípicas. Existen diferentes formas de definir valores atípicos. En este caso, si los outliers son 1.5 veces el rango intercuartílico por encima y debajo del 1 y 3 cuartil, sí hay valores atípicos.

ttl_m_dlrs <- data %>% select('value')
ttl_m_dlrs <- as.numeric(unlist(ttl_m_dlrs[,1]))
summary(ttl_m_dlrs)[2] - 1.5*IQR(ttl_m_dlrs) >= summary(ttl_m_dlrs)[1]
1st Qu. 
  FALSE 
summary(ttl_m_dlrs)[5] + 1.5*IQR(ttl_m_dlrs) <= summary(ttl_m_dlrs)[6]
3rd Qu. 
   TRUE 
summary(ttl_m_dlrs)[2] - 3*IQR(ttl_m_dlrs) >= summary(ttl_m_dlrs)[1]
1st Qu. 
  FALSE 
summary(ttl_m_dlrs)[5] + 3*IQR(ttl_m_dlrs) <= summary(ttl_m_dlrs)[6]
3rd Qu. 
  FALSE 
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr   1.1.4     ✔ stringr 1.5.1
✔ forcats 1.0.0     ✔ tibble  3.2.1
✔ purrr   1.0.2     ✔ tidyr   1.3.0
✔ readr   2.1.5     ── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter()     masks plotly::filter(), stats::filter()
✖ tsibble::interval() masks lubridate::interval()
✖ dplyr::lag()        masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
p <- data %>% as_tibble %>% group_by(years=year(date)) %>%
    summarise(remesas=sum(value)) %>%
    arrange(desc(years))%>%
    mutate(change = (remesas/lead(remesas) - 1) * 100) %>% 
    filter(years > 1995) %>% 
    filter(years < 2023)

mean_growth <- data %>% as_tibble %>% group_by(years=year(date)) %>%
                    summarise(remesas=sum(value)) %>%
                    arrange(desc(years))%>%
                    mutate(change = (remesas/lead(remesas) - 1) * 100) %>% 
                    filter(years > 1995) %>% 
                    filter(years < 2022) %>%
                    summarise(mean(change))

mean_growth <- mean_growth$`mean(change)`

ggplot(p, aes(x=years, y=change)) +
    geom_line() +
    geom_hline(yintercept=mean_growth) +
    geom_hline(yintercept=0) +
    ggtitle('Cambio porcentual por año') + ylab('%') + xlab('Mes')

El crecimiento promedio es de 11.48%.

4) Pronósticos base

Define los periodos de prueba y entrenamiento

Dependiendo de la cantidad de datos y la periodicidad podrías definir diferente cantidad de observaciones. La regla de pulgar es usar 80% de los datos para entrenar y el restante 20% para validar los resultados.

Para esta serie de tiempo 6 meses de validación son suficientes.

También en el libro Forecast: Principles and Practice capítulo 5

train <- data %>% select(value) %>% filter_index("1995 Jan" ~ "2023 Jun")
test <- data %>% select(value) %>% filter_index("2023 Jun" ~ "2023 Dec")
tstng_prds <- 6
frcst_prds <- 6

Seasonal Naive

En el libro Forecast: Principles and Practice capítulo 5, y notebook de clase pronósticos base se muestran diferentes métodos iniciales para hacer estimaciones. Estos métodos iniciales son ligados a la experiencia en la serie y el análisis exploratorio realizado con anterioridad.

Utilizando la funciónfable::SNAIVE para el primer pronóstico base

library(fable)
models_fit <- train %>% 
    model(`Seasonal naive` = SNAIVE(value))
models_tst <- models_fit %>% forecast(h = tstng_prds)
mape_sn <- (models_fit %>% forecast(h = tstng_prds) %>% accuracy(test))$MAPE
snaive_plot <- models_tst %>% autoplot(filter_index(data, "2018 Jan" ~ .)) +
    ggtitle('Seasonal Naive') + ylab('Remesas') + xlab('Mes')

snaive_plot

5) Descomposición

Transformaciones y adjustes

Consulta el libro Forecast: Principles and Practice capítulo 3.1

Ajustar los datos históricos a menudo puede conducir a series temporales más simples. ejemplos de pueden ser ajustes de calendario, ajustes de población, ajustes de inflación y transformaciones matemáticas. El propósito de estos ajustes y transformaciones es simplificar los patrones en los datos históricos eliminando fuentes conocidas de variación o haciendo que el patrón sea más consistente en todo el conjunto de datos. Los patrones más simples suelen ser más fáciles de modelar y conducen a pronósticos más precisos.

Cómo ya se mencionó anteriormente con el histograma, y con observar las magnitudes de los valores al inicio y final de la serie es conveniente una transformación de potencia. El histograma y el sesgo también muestra sesgo negativo. Además, la prueba de normalidad SHAPIRO-WILK (alpha = 0.05)

qqnorm(data$value)
qqline(data$value)

Valor p es menor que Alpha entonces no tenemos una distribución normal. De hecho, estamos lejos de una distribución normal pero el sesgo no esta tan mal siendo 0.5. Queremos lo más acercado a 0 de sesgo.

Aunque se puede entender y usar la transformación box cox para transformar una distribución no normal a una normal, el principal objetivo es corregir sesgos y varianzas desiguales de la siguiente manera:

\[ y(\lambda) =\begin{cases} \frac{(y^\lambda - 1)}{\lambda}& \lambda \neq 0 ,\\ log(y)& \lambda = 0. \end{cases} \]

El lambda óptimo se encuentra cuando se encuentra la distribución con el máximo loglikelihood o con el coeficiente del gráfico de probabilidad de correlación o Shapiro-Wilk.

Bickel, P. J., & Doksum, K. A. (1981). An analysis of transformations revisited. Journal of the American Statistical Association, 76(374), 296–311. DOI

Box, G. E. P., & Cox, D. R. (1964). An analysis of transformations. Journal of the Royal Statistical Society. Series B, Statistical Methodology, 26(2), 211–252. DOI

bc <- EnvStats::boxcox(data$value, lambda=c(-2, 2), optimize=TRUE, objective.name='Log-Likelihood')
bc_data <- EnvStats::boxcoxTransform(data$value, bc$lambda)

skewness(bc_data)
[1] -0.07970027
shapiro.test(bc_data)

    Shapiro-Wilk normality test

data:  bc_data
W = 0.9521, p-value = 3.251e-09
qqnorm(bc_data)
qqline(bc_data)


data <- data %>% mutate('remesas_trn' = bc_data)

Componentes y descomposición STL

Consulta el libro Forecast: Principles and Practice capítulo 3.6

Para estudiar las características de tendencia y estacionalidad se descompone y graficar usando el método STL. La función per de periodicity es la más adecuada al parámetro de suavización estacional s.windows. Es el componente estacional es el más pequeño, siendo la tendencia más significativa.

Podemos observar en el componente estacional captura, que el inicio de año es el más flojito y que, a mediados del año es cuando se envían más remesas.

El competente de tendencia y remanentes observamos y confirmamos lo mencionado anteriormente. A partir del 2004 el envío de remesas, o el registro, aumenta considerablemente y el en 2008 y 2020 el remanente es muy significativo. También, a partir del 2020 el componente remanente se acentúa.

Cleveland, R. B., Cleveland, W. S., McRae, J. E., & Terpenning, I. J. (1990). STL: A seasonal-trend decomposition procedure based on loess. Journal of Official Statistics, 6(1), 3–33. http://bit.ly/stl1990

stl_model = data %>% dplyr::select(remesas_trn) %>% stl(s.window = 'per')
plot(stl_model,main = 'Descomposicón de la serie con STL')

6) Pronósticos base

Define los periodos de prueba y entrenamiento

Dependiendo de la cantidad de datos y la periodicidad podrías definir diferente cantidad de observaciones. La regla de pulgar es usar 80% de los datos para entrenar y el restante 20% para validar los resultados.

Para esta serie de tiempo 6 meses de validación son suficientes.

También en el libro Forecast: Principles and Practice capítulo 5

train <- data %>% select(remesas_trn) %>% filter_index("1995 Jan" ~ "2023 Jun")
test <- data %>% select(remesas_trn) %>% filter_index("2023 Jun" ~ "2023 Dec")
tstng_prds <- 6
frcst_prds <- 6

Seasonal Naive

En el libro Forecast: Principles and Practice capítulo 5, y notebook de clase pronósticos base se muestran diferentes métodos iniciales para hacer estimaciones. Estos métodos iniciales son ligados a la experiencia en la serie y el análisis exploratorio realizado con anterioridad.

Utilizando la funciónfable::SNAIVE para el primer pronóstico base

library(fable)
models_fit <- train %>% 
    model(`Seasonal naive` = SNAIVE(remesas_trn))
models_tst <- models_fit %>% forecast(h = tstng_prds)
mape_sn <- (models_fit %>% forecast(h = tstng_prds) %>% accuracy(test))$MAPE
snaive_plot <- models_tst %>% autoplot(filter_index(data, "2018 Jan" ~ .)) +
    ggtitle('Seasonal Naive') + ylab('Remesas') + xlab('Mes')

snaive_plot

LS0tCnRpdGxlOiAnQW7DoWxpc2lzIGRlIGxvcyBpbmdyZXNvcyBwb3IgcmVtZXNhcyBkZSBNw6l4aWNvJwpzdWJ0aXRsZTogJ0NsYXNlIHNlcmllcyBkZSB0aWVtcG8sIHByaW1hdmVyYSAyMDI0JwphdXRob3I6ICdEYW5pZWwgTnXDsW8sIGRhbmllbC5udW5vQGl0ZXNvLm14JwpkYXRlOiAiRmViIDQsIDIwMjQiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICB0aGVtZTogY29zbW8KICAgIGhpZ2hsaWdodDogdGFuZ28KICBnaXRodWJfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGV2OiBqcGVnCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBkZl9wcmludDogcGFnZWQKLS0tCgpgYGB7ciBzZXR1cCwgZWNobyA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobz0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQgPSA2LCBmaWcud2lkdGggPSA3KQpgYGAKCmBgYHs9aHRtbH0KPHN0eWxlPgouZm9yY2VCcmVhayB7IC13ZWJraXQtY29sdW1uLWJyZWFrLWFmdGVyOiBhbHdheXM7IGJyZWFrLWFmdGVyOiBjb2x1bW47IH0KPC9zdHlsZT4KYGBgCjxjZW50ZXI+IVtdKGh0dHBzOi8vdXBsb2FkLndpa2ltZWRpYS5vcmcvd2lraXBlZGlhL2NvbW1vbnMvZC9kYi9Mb2dvX0lURVNPX25vcm1hbC5qcGcpe3dpZHRoPSIyMCUifTwvY2VudGVyPgoKIyAxKSBEZWZpbmljacOzbgoKIyMgTGEgcHJpbWVyYSBhY3RpdmlkYWQgZGUgY3VhbHF1aWVyIGFuw6FsaXNpcyB5IHByb25vc3RpY28gZXMgZGVmaW5pciBlbCBwcm9ibGVtYQoKRW4gZWwgbGlicm8gRm9yZWNhc3Rpbmc6IFByaW5jaXBsZXMgYW5kIFByYWN0aWNlLCBjYXDDrXR1bG8gcHJpbWVybywgZGVzY3JpYmUgcXVlIGVzIHVuIHByb27Ds3N0aWNvLCBxdWUgc2UgcHVlZGUgcHJvbm9zdGljYXIgeSBjw7NtbyBkZWZpbmlyIGVsIHByb2JsZW1hLCB5IGFsZ3Vub3MgY2Fzb3MgZGUgZXN0dWRpb3MuCgpMZWUgbcOhcyBlbiBlbCBjYXDDrXR1bG8gPGh0dHBzOi8vb3RleHRzLmNvbS9mcHAzL2RldGVybWluaW5nLXdoYXQtdG8tZm9yZWNhc3QuaHRtbD4KCiMjIERlc2NyaXBjacOzbiBkZWwgbGFzIHJlbWVzYXMKCkVzIGVsIGVudsOtbyBkZSBkaW5lcm8gZGUgYXF1ZWxsYXMgcGVyc29uYXMgcXVlIHJhZGljYW4gZW4gb3RyYSBuYWNpw7NuIGEgc3UgcGHDrXMgZGUgb3JpZ2VuLiBQb3IgZWplbXBsbywgbG9zIGVudsOtb3MgZGUgZGluZXJvIHF1ZSByZWFsaXphbiBsb3MgbWV4aWNhbm9zIHF1ZSByYWRpY2FuIGVuIEVzdGFkb3MgVW5pZG9zIHkgQ2FuYWTDoSBhIHN1cyBmYW1pbGlhcyBxdWUgdml2ZW4gZW4gTcOpeGljby4KCkNvbiBlbCBzdXJnaW1pZW50byBkZSBudWV2YXMgaGVycmFtaWVudGFzIHRlY25vbMOzZ2ljYXMgZXMgbcOhcyBzZW5jaWxsbyByZWFsaXphciBlc3RhIHRyYW5zYWNjacOzbiB5IGVsIG7Dum1lcm8gZGUgdXN1YXJpb3MgcXVlIGxhIGhhY2VuIHNlIGhhIGluY3JlbWVudGFkbyBlbiBsb3Mgw7psdGltb3MgYcOxb3MuCgpUYW1iacOpbiBleGlzdGVuIGxhcyByZW1lc2FzIGVudmlhZGFzIHBvciBwZXJzb25hcyBxdWUgc2UgZGVkaWNhbiBhIGxvcyBuZWdvY2lvcyB5IHRpZW5lbiBxdWUgcGFnYXIgc3VlbGRvcyBhIGxvcyBlbXBsZWFkb3MgY29udHJhdGFkb3MgZW4gZWwgZXh0ZXJpb3IsIHBvciBlamVtcGxvLiBPdHJhIHRyYW5zZmVyZW5jaWEgbXV5IGNvbcO6biBlcyBwYXJhIGVzdHVkaWFudGVzIHF1ZSBubyBwdWVkZW4gdHJhYmFqYXIgeSBuZWNlc2l0YW4gbWFudGVuZXJzZSBlbiBvdHJvIHBhw61zIG1pZW50cmFzIGVzdHVkaWFuLgoKTGFzIHJlbWVzYXMgc29uIGxhIHNlZ3VuZGEgZnVlbnRlIGRlIGRpdmlzYXMgbcOhcyBpbXBvcnRhbnRlIGRlIE3DqXhpY28gZGVzcHXDqXMgZGUgbG9zIGluZ3Jlc29zIHBvciBwZXRyw7NsZW8uIFJlcHJlc2VudGFuIGNlcmNhIGRlIDMlIGRlbCBQSUIsIDUwJSBkZSBsYXMgZXhwb3J0YWNpb25lcyBwZXRyb2xlcmFzLCAxMzUlIGRlIGxhIGludmVyc2nDs24gZXh0cmFuamVyYSBkaXJlY3RhIHkgMTg5JSBkZSBsb3MgaW5ncmVzb3MgZGUgdmlhamVyb3MgaW50ZXJuYWNpb25hbGVzLgoKTG9zIGluZ3Jlc29zIHBvciByZW1lc2FzIHByb3ZlbmllbnRlcyBkZWwgZXh0ZXJpb3IgYXNjZW5kaWVyb24gYSA0LDc2MCBtaWxsb25lcyBkZSBkw7NsYXJlcyBlbiBkaWNpZW1icmUgZGUgMjAyMSwgbG8gcXVlIGltcGxpY8OzIHVuIGF1bWVudG8gYW51YWwgZGUgMzAuNCUuCgpQb3Igc3UgcGFydGUsIGxhcyByZW1lc2FzIGVudmlhZGFzIHBvciByZXNpZGVudGVzIGVuIE3DqXhpY28gYWwgZXh0ZXJpb3IgbW9zdHJhcm9uIHVuIGNyZWNpbWllbnRvIGFudWFsIGRlIDEuOCUsIGFsIGFsY2FuemFyIHVuIG5pdmVsIGRlIDExNCBtaWxsb25lcyBkZSBkw7NsYXJlcy4KCkNvbiBlc3RvcyByZXN1bHRhZG9zLCBlbCBzdXBlcsOhdml0IGRlIGxhIGN1ZW50YSBkZSByZW1lc2FzIGRlIE3DqXhpY28gY29uIGVsIHJlc3RvIGRlbCBtdW5kbyBmdWUgZGUgNCw2NDYgbWlsbG9uZXMgZGUgZMOzbGFyZXMsIG1heW9yIGFsIGRlIDMsNTM4IG1pbGxvbmVzIGRlIGTDs2xhcmVzIHF1ZSBzZSBwcmVzZW50w7MgZW4gZGljaWVtYnJlIGRlIDIwMjAuCgpDb24gc2VyaWVzIGRlc2VzdGFjaW9uYWxpemFkYXMsIGVuIGVsIMO6bHRpbW8gbWVzIGRlIDIwMjEgbG9zIGluZ3Jlc29zIHkgZWdyZXNvcyBwb3IgcmVtZXNhcyBleGhpYmllcm9uIHJldHJvY2Vzb3MgbWVuc3VhbGVzIGRlIDEuOSB5IDIuMyUsIGVuIGlndWFsIG9yZGVuLiBBc8OtLCBlbiBkaWNpZW1icmUgZGUgMjAyMSBlbCBzdXBlcsOhdml0IGRlIGxhIGN1ZW50YSBkZSByZW1lc2FzIHNlIHNpdHXDsyBlbiA0LDYwMCBtaWxsb25lcyBkZSBkw7NsYXJlcywgcXVlIHNlIGNvbXBhcmEgY29uIGVsIGRlIDQsNjg3IG1pbGxvbmVzIGRlIGTDs2xhcmVzIHF1ZSBzZSBvYnNlcnbDsyBlbiBub3ZpZW1icmUgZGUgMjAyMS4KClBhcmEgbGEgdG90YWxpZGFkIGRlIDIwMjEsIGVsIHZhbG9yIGRlIGxvcyBpbmdyZXNvcyBwb3IgcmVtZXNhcyBmdWUgZGUgNTEsNTk0IG1pbGxvbmVzIGRlIGTDs2xhcmVzLCBtb250byBzdXBlcmlvciBhbCBkZSA0MCw2MDUgbWlsbG9uZXMgZGUgZMOzbGFyZXMgcmVwb3J0YWRvIGVuIDIwMjAgeSBxdWUgc2lnbmlmaWPDsyB1bmEgZXhwYW5zacOzbiBhbnVhbCBkZSAyNy4xJS4KCkR1cmFudGUgMjAyMSwgZWwgOTguOSUgZGVsIHRvdGFsIGRlIGxvcyBpbmdyZXNvcyBwb3IgcmVtZXNhcyBzZSByZWFsaXrDsyBhIHRyYXbDqXMgZGUgdHJhbnNmZXJlbmNpYXMgZWxlY3Ryw7NuaWNhcywgYWwgdWJpY2Fyc2UgZW4gNTEsMDQ1IG1pbGxvbmVzIGRlIGTDs2xhcmVzLiBQb3Igc3UgcGFydGUsIGxhcyByZW1lc2FzIGVmZWN0dWFkYXMgZW4gZWZlY3Rpdm8geSBlc3BlY2llMiB5IGxhcyBtb25leSBvcmRlcnMgcmVwcmVzZW50YXJvbiBlbCAwLjcgeSAwLjQlIGRlbCBtb250byB0b3RhbCwgcmVzcGVjdGl2YW1lbnRlLCBhbCByZWdpc3RyYXIgbml2ZWxlcyBkZSAzMzMgeSAyMTYgbWlsbG9uZXMgZGUgZMOzbGFyZXMsIGVuIGVsIG1pc21vIG9yZGVuLgoKTG9zIGVncmVzb3MgcG9yIHJlbWVzYXMgc3VtYXJvbiAxLDA1NyBtaWxsb25lcyBkZSBkw7NsYXJlcyBlbiAyMDIxLCBjaWZyYSBtYXlvciBhIGxhIGRlIDg5OSBtaWxsb25lcyBkZSBkw7NsYXJlcyBvYnNlcnZhZGEgZW4gMjAyMCB5IHF1ZSBpbXBsaWPDsyB1biBpbmNyZW1lbnRvIGFudWFsIGRlIDE3LjYlLgoKQ29uIGVzdG9zIHJlc3VsdGFkb3MsIGVsIHNhbGRvIHN1cGVyYXZpdGFyaW8gZGUgbGEgY3VlbnRhIGRlIHJlbWVzYXMgZW4gMjAyMSBmdWUgZGUgNTAsNTM3IG1pbGxvbmVzIGRlIGTDs2xhcmVzLCBjaWZyYSBzdXBlcmlvciBhIGxhIGRlIDM5LDcwNiBtaWxsb25lcyBkZSBkw7NsYXJlcyByZXBvcnRhZGEgZW4gMjAyMCB5IHF1ZSByZXByZXNlbnTDsyB1biBhdmFuY2UgYW51YWwgZGUgMjcuMyUuCgojIyMgRGF0b3MKCkJhbmNvIGRlIE3DqXhpY28gcmVnaXN0cmEgbGFzIHJlbWVzYXMgY29tbyBwYXJ0ZSBkZSBsYSBiYWxhbnphIGRlIHBhZ29zIHkgdGllbmUgcmVnaXN0cm8gbWVuc3VhbCBkZXNkZSAxOTk1LgoKTG9zIGRhdG9zIGRlIEJhbnhpY28gcHVlZGVuIHNlciBkZXNjYXJnYWRvcyBlbiBlbCBzaWd1aWVudGUgW2VubGFjZV0oaHR0cHM6Ly93d3cuYmFueGljby5vcmcubXgvU2llSW50ZXJuZXQvY29uc3VsdGFyRGlyZWN0b3Jpb0ludGVybmV0QWN0aW9uLmRvP2FjY2lvbj1jb25zdWx0YXJDdWFkcm8maWRDdWFkcm89Q0U4MSZsb2NhbGU9ZXNjKQoKIyMjIERldGVybWluYXIgcXVlIHByb25vc3RpY2FyCgpTZSBhbmFsaXphcmEgZWwgaW5ncmVzbyB0b3RhbCBkZSByZW1lc2FzLCBjb21vIHNlIG11ZXN0cmEgZW4gbGEgY2FwdHVyYSBzaWd1aWVudGUuCgohW10oLi9pbWFnZXMvYmFueGljby5wbmcpCgojIyMgUG9yIHF1ZSBlcyBpbXBvcnRhbnRlIGFuYWxpemFyIHkgcHJvbm9zdGljYXIgZW4gZWwgY29udGV4dG8gc29jaWFsCgpFbCBmbHVqbyBkZSByZW1lc2FzIGludGVybmFjaW9uYWxlcyB0aWVuZSB1biBlZmVjdG8gaW1wb3J0YW50ZSBzb2JyZSBsYSBhY3RpdmlkYWQgZWNvbsOzbWljYSBlbiBhbGd1bmFzIGVudGlkYWRlcyBxdWUgc2UgbG9jYWxpemFuIGVuIGxhcyByZWdpb25lcyBjZW50cmFsZXMgeSBlbCBzdXIgZGVsIHBhw61zLiBFc3RvIGNvbmR1am8gYSBxdWUgZWwgaW5jcmVtZW50byBvYnNlcnZhZG8gZW4gbGFzIHJlbWVzYXMgaGF5YSBpbmR1Y2lkbyBlbiAyMDE2IHVuIG1heW9yIGNyZWNpbWllbnRvIGVjb27Ds21pY28gZW4gZXN0YXMgcmVnaW9uZXMuCgpFbiBlZmVjdG8sIGNvbW8gcmVzdWx0YWRvIGRlIGxvcyBwYXRyb25lcyBkZSBnYXN0byBkZSBsb3MgaG9nYXJlcywgZGljaGFzIGVudGlkYWRlcyB0aWVuZGVuIGEgc2VyIG3DoXMgcHJvcGVuc2FzIGEgY29uY2VudHJhciBlbCBpbXBhY3RvIGRlIGxhcyByZW1lc2FzIGVuIGxhcyBhY3RpdmlkYWRlcyBjb21lcmNpYWxlcyB5IGxvcyBzZXJ2aWNpb3MuIEFkaWNpb25hbG1lbnRlLCBsb3MgZmx1am9zIGRlIHJlbWVzYXMgY29udHJpYnV5ZW4gYSBzdWF2aXphciBlbCBpbmdyZXNvIGRlIGxvcyBob2dhcmVzIGFudGUgY2hvcXVlcyBzb2JyZSBsYSBhY3RpdmlkYWQgZWNvbsOzbWljYSwgZW4gcGFydGljdWxhciBlbiBlbCBzZWN0b3IgYWdyb3BlY3VhcmlvLgoKKipMYXMgcmVtZXNhcyBzb24gbGEgc2VndW5kYSBmdWVudGUgZGUgZGl2aXNhcyBtw6FzIGltcG9ydGFudGUgZGUgTcOpeGljby4gRW4gbG9zIMO6bHRpbW9zIGHDsW9zIGxhcyByZW1lc2FzIGhhbiBhbGNhbnphZG8gbcOheGltb3MgaGlzdMOzcmljb3MsIGFkZW3DoXMsIGhhbiBvYnRlbmlkbyBtYXlvciBhdGVuY2nDs24gcG9yIGxhcyByZWNpZW50ZXMgaW52ZXN0aWdhY2lvbmVzIHF1ZSBzZcOxYWxhbiBjw7NtbyBjw6FydGVsZXMgZGVsIG5hcmNvIGxhdmFuIGRpbmVybyB2w61hIHJlbWVzYXMuKioKCiMgMikgRGF0b3MKCiMjIEltcG9ydGFyCgpFbiBsYXMgc2lndWllbnRlcyBjZWxkYXMgc2UgbXVlc3RhbiBsb3MgcGFzb3MgcGFyYSBpbXBvcnRhciBsb3MgZGF0b3MgZGVzZGUgbWkgZXNwYWNpbyBkZSB0cmFiYWpvLiBQb3IgcXVlIGVzIHVuIGFyY2hpdm8gZW4gZm9ybWF0byBFeGNlbCwgbGEgbGlicmVyw61hIHVzYWRhIGVzIGByZWFkeGxgLgoKTGVlIG3DoXMgZW4gZWwgbm90ZWJvb2sgaW50cm9kdWN0b3JpbyB2aXN0byBlbiBjbGFzZTogW3RpZHl2ZXJzZV0oaHR0cHM6Ly9pdGVzby5pbnN0cnVjdHVyZS5jb20vY291cnNlcy8zNjY3My9maWxlcy83MDM4Mzg2P21vZHVsZV9pdGVtX2lkPTE1Mjc2NTgmZmRfY29va2llX3NldD0xKSwgc2VjY2nDs24gKkRhdGEgc2NpZW5jZSB3b3JrZmxvdyosIHBhc28gKjEgSW1wb3J0IERhdGEqLgoKVGFtYmnDqW4gZW4gZWwgbGlicm8gW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZGxleS5uei9pbXBvcnQpIGNhcMOtdHVsbyAyMC4KCiFbXSguL2ltYWdlcy9pbXBvcnQlMjB0aWR5dmVyc2UucG5nKQoKYGBge3J9CmxpYnJhcnkocmVhZHhsKQoKI3Jhd19kYXRhID0gcmVhZF94bHN4KHBhdGggPSAiL1VzZXJzL2RhbmllbG51bm8vR2l0SHViL3RpbWVfc2VyaWVzX3MyMDI0L0FuYWxpc2lzL3JlbWVzYXMgYmFueGljby54bHN4Iiwgc2hlZXQgPSAiSG9qYTEiLCBjb2xfbmFtZXMgPSBGQUxTRSkKcmF3X2RhdGEgPSByZWFkX3hsc3gocGF0aCA9ICJ+L0dpdEh1Yi90aW1lX3Nlcmllc19zMjAyNC9BbmFsaXNpcy9yZW1lc2FzL3JlbWVzYXMgYmFueGljby54bHN4Iiwgc2hlZXQgPSAiSG9qYTEiLCBjb2xfbmFtZXMgPSBGQUxTRSkKCmhlYWQocmF3X2RhdGEsIDIwKQpgYGAKCiMjIEVsaW1pbmFyIGZpbGFzCgpMb3MgZGF0b3Mgbm8gaW5pY2lhbiBoYXN0YSBsYSBmaWxhIDE4LiBVc2FuZG8gYGRwbHlyOjpzbGljZWAgc2UgcHVlZGVuIGVsaW1pbmFuIGxhcyBwcmltZXJhcyAxOCBmaWxhcy4KCkxlZSBtw6FzIGVuIGVsIG5vdGVib29rIGludHJvZHVjdG9yaW8gdmlzdG8gZW4gY2xhc2U6IFt0aWR5dmVyc2VdKGh0dHBzOi8vaXRlc28uaW5zdHJ1Y3R1cmUuY29tL2NvdXJzZXMvMzY2NzMvZmlsZXMvNzAzODM4Nj9tb2R1bGVfaXRlbV9pZD0xNTI3NjU4JmZkX2Nvb2tpZV9zZXQ9MSksIHNlY2Npw7NuICpEYXRhIHNjaWVuY2Ugd29ya2Zsb3cqLCBwYXNvICozIHVuZGVyc3RhbmQgeW91ciBkYXRhKi4KCiFbXSguL2ltYWdlcy9kcGx5ci5wbmcpCgpUYW1iacOpbiBlbiBlbCBsaWJybyBbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkbGV5Lm56L2ltcG9ydCkgY2Fww610dWxvIDI3LgoKYGBge3J9CiNyYXdfZGF0YSA9IHJhd19kYXRhWy0oMToxOCksIF0KZGF0YSA9IGRwbHlyOjpzbGljZShyYXdfZGF0YSwgLSgxOjE4KSkKaGVhZChkYXRhLCAyKQpgYGAKCiMjIFJlbm9tYnJhIGxhcyBjb2x1bW5hcwoKTGFzIGRpbWVuc2lvbmVzIGVzdMOhbiBub21icmFkYXMgY29tbyAqLi4uMSogeSAqLi4uMiosIHBvciBsbyB0YW50byBlcyBjb252ZW5pZW50ZSByZW5vbWJyYXJsYXMgc2luIGVzcGFjaW9zIG5pIGNhcmFjdGVyZXMgZXNwZWNpYWxlcy4KCmBgYHtyfQpjb2xuYW1lcyhkYXRhKSA9IGMoJ2RhdGUnLCAndmFsdWUnKQpoZWFkKGRhdGEsIDIpCmBgYAoKIyMgQ2FtYmlhIGVsIHRpcG8gZGUgZGF0byBkZSBsYXMgY29sdW1uYXMKCkxhcyBjb2x1bW5hcyBzb24gYGNocmAgcGVybyBkYXRlIHRpZW5lIHF1ZSBzZXIgdW5hIGZlY2hhIG1lbnN1YWwgeSB2YWx1ZSBzb24gbWlsbG9uZXMgZGUgZMOzbGFyZXMuIFV0aWxpemEgYGx1YnJpZGF0ZWAgcGFyYSBoYWNlciBsYSB0cmFuc2Zvcm1hY2nDs24gZGUgbGEgZmVjaGEgbyBSIGLDoXNpY28uCgpMZWUgbcOhcyBlbiBlbCBub3RlYm9vayBpbnRyb2R1Y3RvcmlvIHZpc3RvIGVuIGNsYXNlOiBbdGlkeXZlcnNlXShodHRwczovL2l0ZXNvLmluc3RydWN0dXJlLmNvbS9jb3Vyc2VzLzM2NjczL2ZpbGVzLzcwMzgzODY/bW9kdWxlX2l0ZW1faWQ9MTUyNzY1OCZmZF9jb29raWVfc2V0PTEpLCBzZWNjacOzbiAqRGF0YSBzY2llbmNlIHdvcmtmbG93KiwgcGFzbyAqMyB1bmRlcnN0YW5kIHlvdXIgZGF0YTogZGF0YSB0cmFuc2Zvcm1hdGlvbiouCgpUYW1iacOpbiBlbiBlbCBsaWJybyBbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkbGV5Lm56L2RhdGV0aW1lcykgY2Fww610dWxvIDE3LgoKIyMjIFRyYW5zZm9ybWEgZWwgdGlwbyB0ZXh0byBjw7NtbyBudW3DqXJpY28KCmBgYHtyfQpkYXRhJGRhdGUgPSBhcy5udW1lcmljKGRhdGEkZGF0ZSkKYGBgCgojIyMgVHJhbnNmb3JtYSBlbCBuw7ptZXJvIGEgZmVjaGEgdXRpbGl6YW5kbyBlbCBhcmd1bWVudG8gb3JpZ2luCgpFbCBuw7ptZXJvIHJlcHJlc2VudGEgdW4gZMOtYSBlbiBsYSBzZXJpZSBxdWUgaW5pY2lhIGVsIHByaW1lcm8gZGUgZW5lcm8gZGUgMTk5MC4gUG9yIGxvIHRhbnRvIHV0aWxpemFtb3MgZWwgYXJndW1lbnRvIG9yaWdpbiBxdWUgaW5kaWNhIGVsIGluaWNpbyBkZSBsYSBzZXJpZS4KCmBgYHtyfQpkYXRhJGRhdGUgPSBhcy5EYXRlKGRhdGEkZGF0ZSwgb3JpZ2luID0gIjE4OTktMTItMzAiKQpgYGAKCiMjIyBDcmVhIHVuYSBzZWN1ZW5jw61hIGV4cGxpY2l0YSBsYSBwZXJpb2RpY2lkYWQgbWVuc3VhbAoKYGBge3J9CmRhdGEkZGF0ZSA9IHNlcShmcm9tID0gbWluKGRhdGEkZGF0ZSksIHRvID0gbWF4KGRhdGEkZGF0ZSksIGJ5ID0gIjEgbW9udGgiKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeSh0c2liYmxlKQpkYXRhJGRhdGUgPSB5ZWFybW9udGgoZGF0YSRkYXRlKQpoZWFkKGRhdGEsIDIpCmBgYAoKIyMjIENhbWJpYSBlbCB0aXBvIGRlIGRhdG8gZGUgbGEgY29sdW1uYSB2YWx1ZQoKYGBge3J9CmRhdGEkdmFsdWUgPSBhcy5udW1lcmljKGRhdGEkdmFsdWUpCmhlYWQoZGF0YSwgMikKYGBgCgojIyBDcmVhIHVuIHRzaWJibGUKClVzYW5kbyBgdHNpYmJsZTo6YXNfdHNpYmJsZSgpYCBhc2lnbmEgbGEgZmVjaGEgY29tbyBpbmRleC4gRW4gZXN0ZSBjYXNvIGBrZXlgIG5vIGVzIG5lY2VzYXJpbyBwZXJvIGRlY2lkZSBzaSBlcyBpbXBvcnRhbnRlIHBhcmEgdHUgc2VyaWUuCgpMZWUgbcOhcyBlbiBlbCBub3RlYm9vayBpbnRyb2R1Y3RvcmlvIHZpc3RvIGVuIGNsYXNlOiBbdGlkeXZlcnNlXShodHRwczovL2l0ZXNvLmluc3RydWN0dXJlLmNvbS9jb3Vyc2VzLzM2NjczL2ZpbGVzLzcwMzgzODY/bW9kdWxlX2l0ZW1faWQ9MTUyNzY1OCZmZF9jb29raWVfc2V0PTEpLCBzZWNjacOzbiAqRGF0YSBzY2llbmNlIHdvcmtmbG93KiwgcGFzbyAqMiBUaWR5IERhdGEqLiBZIGVsIGVqZW1wbG8gMS4KClRhbWJpw6luIGxhIGRvY3VtZW50YWNpw7NuIFt0c2liYmxlXShodHRwczovL3RzaWJibGUudGlkeXZlcnRzLm9yZy8pIHkgZWwgbGlicm8gW0ZvcmVjYXN0OiBQcmluY2lwbGVzIGFuZCBQcmFjdGljZV0oaHR0cHM6Ly9vdGV4dHMuY29tL2ZwcDMvdHNpYmJsZXMuaHRtbCkgY2Fww610dWxvIDIuMQoKYGBge3J9CmRhdGEgPSBhc190c2liYmxlKGRhdGEsIGluZGV4PWRhdGUsIHJlZ3VsYXI9VFJVRSkKaGVhZChkYXRhLCAyKQpgYGAKCmBgYHtyfQppbnRlcnZhbChkYXRhKQpgYGAKCiMjIyBWYWxvcmVzIGZhbHRhbnRlcyB5IGZhY3RvcmVzCklkZW50aWZpY2Egc2kgdHUgc2VyaWUgZGUgdGllbXBvIHRpZW5lIHZhbG9yZXMgZmFsdGFudGVzIG8gZmFjdG9yZXMgeSBoYXMgbGFzIHRyYW5zZm9ybWFjaW9uZXMgY29ycmVzcG9uZGllbnRlcyBjb24gYXl1ZGEgZGVsIGxpYnJvIFtSIGZvciBkYXRhIHNjaWVuY2UgLSBUcmFuc2Zvcm1dKGh0dHBzOi8vcjRkcy5oYWRsZXkubnovdHJhbnNmb3JtKS4KCgojIDMpIEFuw6FsaXNpcwoKIyMgVmlzdWFsaXphY2nDs24gZGUgbGEgc2VyaWUKClV0aWxpemEgZ2dwbG90MiBwYXJhIGdyw6FmaWNhciBsYSBzZXJpZQoKTGVlIG3DoXMgZW4gZWwgbm90ZWJvb2sgaW50cm9kdWN0b3JpbyB2aXN0byBlbiBjbGFzZTogW3RpZHl2ZXJzZV0oaHR0cHM6Ly9pdGVzby5pbnN0cnVjdHVyZS5jb20vY291cnNlcy8zNjY3My9maWxlcy83MDM4Mzg2P21vZHVsZV9pdGVtX2lkPTE1Mjc2NTgmZmRfY29va2llX3NldD0xKSwgc2VjY2nDs24gKkRhdGEgc2NpZW5jZSB3b3JrZmxvdyosIHBhc28gKjMgVW5kZXJzdGFuZCB5b3VyIGRhdGEgLSB2aXN1YWxpemF0aW9uKi4KClZlIGxvcyBlamVtcGxvcyB5IGV4cGxpY2FjaW9uZXMgdmlzdGFzIGVuIGNsYXNlOiBbZ2dwbG90Ml0oaHR0cHM6Ly9pdGVzby5pbnN0cnVjdHVyZS5jb20vY291cnNlcy8zNjY3My9maWxlcy83MDE0NTAxP21vZHVsZV9pdGVtX2lkPTE1MjU0MzAmZmRfY29va2llX3NldD0xKSwgc2VjY2nDs24gKkdyw6FmaWNhcyBjb24gZ2dwbG90MiouCgohW10oLi9pbWFnZXMvZ2dwbG90Mm5iLnBuZykKClRhbWJpw6luIGVsIGxpYnJvIFtGb3JlY2FzdDogUHJpbmNpcGxlcyBhbmQgUHJhY3RpY2VdKGh0dHBzOi8vb3RleHRzLmNvbS9mcHAzL3RpbWUtcGxvdHMuaHRtbCkgY2Fww610dWxvIDIuMgoKIVtdKC4vaW1hZ2VzL2NhcDIxLnBuZykKCiMjIyBUaW1lIHBsb3QKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZmVhc3RzKQpmZWFzdHM6OmF1dG9wbG90KGRhdGEpICsgZ2d0aXRsZSgnUmVtZXNhcyBwb3IgbWVzJykgKyB5bGFiKCdNaWxsb25lcyBkZSBkw7NsYXJlcycpICsgeGxhYignRmVjaGEnKQpgYGAKCgojIyMgUGF0cm9uZXMKCkdyw6FmaWNhbWVudGUgcHJlc2VudGEgKip0ZW5kZW5jaWEqKiwgKiplc3RhY2lvbmFsaWRhZCoqIHkgaGV0ZXJvc2NlZGFzdGljaWRhZC4gUGFyZWNlIHByZXNlbnRhciAqKmNpY2xvcyoqIHJlbGFjaW9uYWRvcyBhIGxhIGFjdGl2aWRhZCBlY29uw7NtaWNhLgoKQ29uc3VsdGEgZWwgbGlicm8gW0ZvcmVjYXN0OiBQcmluY2lwbGVzIGFuZCBQcmFjdGljZV0oaHR0cHM6Ly9vdGV4dHMuY29tL2ZwcDMvdHNwYXR0ZXJucy5odG1sKSBjYXDDrXR1bG8gMi4zCgojIyMgR3LDoWZpY2EgZXN0YWNpb25hbGVzCgpVbmEgZ3LDoWZpY2EgZXN0YWNpb25hbCBlcyBsbyBtaXNtbyBxdWUgdW4gdGltZSBwbG90IHBlcm8gZ3JhZmljYWRhIHVzYW5kbyBsb3MgcGVyaW9kb3MgZXN0YWNpb25hbGVzLiBFbiBlc3RlIGNhc28gbGEgZXN0YWNpb25hbGlkYWQgZXMgbWVuc3VhbC4KCkNvbnN1bHRhIGVsIGxpYnJvIFtGb3JlY2FzdDogUHJpbmNpcGxlcyBhbmQgUHJhY3RpY2VdKGh0dHBzOi8vb3RleHRzLmNvbS9mcHAzL3NlYXNvbmFsLXBsb3RzLmh0bWwpIGNhcMOtdHVsbyAyLjQKCmBgYHtyfQpkYXRhICU+JSBnZ19zZWFzb24odmFsdWUsIGxhYmVscyA9ICJib3RoIikgKwogICAgZ2d0aXRsZSgnUmVtZXNhcyBwb3IgYcOxbycpICsgeWxhYignTWlsbG9uZXMgZGUgZMOzbGFyZXMnKSArIHhsYWIoJ01lcycpCmBgYAoKVXRpbGl6YSBgcGxvdGx5OjpnZ3Bsb3RseSgpYCBoYWNlciBncsOhZmljb3MgaW50ZXJhY3Rpdm9zCgpgYGB7cn0Kc3VwcHJlc3NXYXJuaW5ncyhsaWJyYXJ5KHBsb3RseSkpCgp5ZWFybHlfZGF0YV9wbG90ID0gZGF0YSAlPiUgZ2dfc2Vhc29uKHZhbHVlLCBsYWJlbHMgPSAiYm90aCIpICsKICAgIGdndGl0bGUoJ1JlbWVzYXMgcG9yIGHDsW8nKSArIHlsYWIoJ01pbGxvbmVzIGRlIGTDs2xhcmVzJykgKyB4bGFiKCdNZXMnKQoKZ2dwbG90bHkoeWVhcmx5X2RhdGFfcGxvdCkKYGBgCgojIyMgU3ViIGdyw6FmaWNhcyBlc3RhY2lvbmFsZXMKClVuIGdyw6FmaWNvIGFsdGVybmF0aXZvIHF1ZSBlbmZhdGl6YSBsb3MgcGF0cm9uZXMgZXN0YWNpb25hbGVzIGVzIGFxdWVsIGVuIGVsIHF1ZSBsb3MgZGF0b3MgZGUgY2FkYSB0ZW1wb3JhZGEgc2UgcmVjb3BpbGFuIGVuIG1pbmlncsOhZmljb3MgZGUgdGllbXBvIHNlcGFyYWRvcy4KCkNvbnN1bHRhIGVsIGxpYnJvIFtGb3JlY2FzdDogUHJpbmNpcGxlcyBhbmQgUHJhY3RpY2VdKGh0dHBzOi8vb3RleHRzLmNvbS9mcHAzL3N1YnNlcmllcy5odG1sKSBjYXDDrXR1bG8gMi41CgpgYGB7cn0Kc3Vic2VyaWVzX3Bsb3QgPSBkYXRhICU+JSBnZ19zdWJzZXJpZXModmFsdWUpCmdncGxvdGx5KHN1YnNlcmllc19wbG90KQpgYGAKCiMjIyBHcsOhZmljbyBkZSByZXphZ29zCgpFc3RvcyBncsOhZmljb3Mgc29uIGdyw6FmaWNvcyBkZSBkaXNwZXJzacOzbiBldmFsdWFkb3MgZW4gbG9zIHJlemFnb3MgZGUgbGEgbWlzbWEgc2VyaWUgcXVlIG1pZGVuIGxhIGNvcnJlbGFjacOzbiBlbnRyZSBwZXJpb2Rvcy4gRW4gb3RyYXMgcGFsYWJyYXMsIHBhcmEgZXN0YSBzZXJpZSBkZSB0aWVtcG8gbWVuc3VhbCwgbWlkZSBsYSByZWxhY2nDs24gZGUgdW4gbWVzIGVuIGVsIHRpZW1wbyBjb250cmEgdW4gbWVzIChuIGxhZ3MpIGRlbCBwYXNhZG8uCgpDb25zdWx0YSBlbCBsaWJybyBbRm9yZWNhc3Q6IFByaW5jaXBsZXMgYW5kIFByYWN0aWNlXShodHRwczovL290ZXh0cy5jb20vZnBwMy9sYWctcGxvdHMuaHRtbCkgY2Fww610dWxvIDIuNwoKYGBge3J9CmxhZ3NfcGxvdHMgPSBkYXRhICU+JSBmaWx0ZXIoeWVhcihkYXRlKSA+IDIwMTgpICU+JSBnZ19sYWcodmFsdWUsIGdlb20gPSAicG9pbnQiLCBsYWdzID0gMToxMikgKyBsYWJzKHggPSAibGFnKFJlbWVzYSwgaykiKQoKc3VwcHJlc3NXYXJuaW5ncyhnZ3Bsb3RseShsYWdzX3Bsb3RzKSkKYGBgCgojIyMgQXV0b2NvcnJlbGFjacOzbgoKQXPDrSBjb21vIGxhIGNvcnJlbGFjacOzbiBtaWRlIGVsIGFsY2FuY2UgZGUgdW5hIHJlbGFjacOzbiBsaW5lYWwgZW50cmUgZG9zIHZhcmlhYmxlcywgbGEgYXV0b2NvcnJlbGFjacOzbiBtaWRlIGxhIHJlbGFjacOzbiBsaW5lYWwgZW50cmUgdmFsb3JlcyByZXphZ2Fkb3MgZGUgdW5hIHNlcmllIHRlbXBvcmFsLgoKQ29uc3VsdGEgZWwgbGlicm8gW0ZvcmVjYXN0OiBQcmluY2lwbGVzIGFuZCBQcmFjdGljZV0oaGh0dHBzOi8vb3RleHRzLmNvbS9mcHAzL2FjZi5odG1sKSBjYXDDrXR1bG8gMi44CgpgYGB7cn0KZGF0YSAlPiUgQUNGKHZhbHVlLCBsYWdfbWF4ID0gMTIpCmBgYAoKYGBge3J9CmRhdGEgJT4lIEFDRih2YWx1ZSwgbGFnX21heCA9IDI0KSAlPiUgYXV0b3Bsb3QoKSArIGxhYnModGl0bGU9J1JlbWVzYXMgcG9yIGHDsW8nKQpgYGAKCkN1YW5kbyBsb3MgZGF0b3MgdGllbmVuICoqdGVuZGVuY2lhKiosIGxhcyBhdXRvY29ycmVsYWNpb25lcyBwYXJhIGRlc2Zhc2VzIHBlcXVlw7FvcyB0aWVuZGVuIGEgc2VyIGdyYW5kZXMgeSBwb3NpdGl2YXMgcG9ycXVlIGxhcyBvYnNlcnZhY2lvbmVzIGNlcmNhbmFzIGVuIGVsIHRpZW1wbyB0YW1iacOpbiBsbyBzb24gZW4gdmFsb3IuIFBvciBsbyB0YW50bywgZWwgQUNGIGRlIHVuYSBzZXJpZSB0ZW1wb3JhbCBjb24gdGVuZGVuY2lhIHRpZW5kZSBhIHRlbmVyIHZhbG9yZXMgcG9zaXRpdm9zIHF1ZSBkaXNtaW51eWVuIGxlbnRhbWVudGUgYSBtZWRpZGEgcXVlIGF1bWVudGFuIGxvcyByZXphZ29zLgoKQ3VhbmRvIGxvcyBkYXRvcyBzb24gKiplc3RhY2lvbmFsZXMqKiwgbGFzIGF1dG9jb3JyZWxhY2lvbmVzIHNlcsOhbiBtYXlvcmVzIHBhcmEgbG9zIHJlemFnb3MgZXN0YWNpb25hbGVzIChlbiBtw7psdGlwbG9zIGRlbCBwZXLDrW9kbyBlc3RhY2lvbmFsKSBxdWUgcGFyYSBvdHJvcyByZXphZ29zLgoKU2VyYSBpbXBvcnRhbnRlIHJlYWxpemFyIGxhcyBtaXNtYXMgZ3LDoWZpY2FzIHVuYSB2ZXogcXVlIGxhIHNlcmllIHNlYSBlc3RhY2lvbmFsLgoKQWRlbcOhcyBkZSBsbyBkZXNjcml0byBlbiBsYSBwcmltZXJhIHBhcnRlIGRlbCBkb2N1bWVudG8sIGNvbiBsYXMgZ3LDoWZpY2FzIHBvZGVtb3Mgb2JzZXJ2YXIgbG8gc2lndWllbnRlOgoKR3LDoWZpY2FtZW50ZSBwcmVzZW50YSAqKnRlbmRlbmNpYSoqLCAqKmVzdGFjaW9uYWxpZGFkKiouIFBhcmVjZSBwcmVzZW50YXIgKipjaWNsb3MqKiByZWxhY2lvbmFkb3MgYSBsYSBhY3RpdmlkYWQgZWNvbsOzbWljYS4KCmVzIGludGVyZXNhbnRlIG9ic2VydmFyIGNvbiBlc3RlIGdyw6FmaWNvIHF1ZSBhIHBhcnRpciBkZWwgYcOxbyAyMDA0IGxvcyBkYXRvcyBzZSB2ZW4gc2VwYXJhZG9zLCBlcyBkZWNpciwgbGEgYW1wbGl0dWQgZGUgbG9zIGRhdG9zIHNlIHZ1ZWx2ZSBtw6FzIGdyYW5kZSBlbiBjYWRhIGHDsW8gZGVzcHXDqXMgcXVlIHBhc2EuIFBvZGVtb3MgY29uY2x1aXIgdHJlcyBjb3NhcyBjb24gZXN0bzoKCi0gTG9zIHByaW1lcm9zIHNpZXRlIHUgb2NobyBhw7FvcyBkZSBsYSBzZXJpZSBoYXkgY3JlY2ltaWVudG8sIHBlcm8gYSBwYXJ0aXIgZGVsIDIwMDMgZWwgY3JlY2ltaWVudG8gZXMgZXhwb25lbmNpYWwgZGUgY8OzbW8gZXJhIGFudGVzLgotIEVuIGVzYXMgZmVjaGFzIHNlIHZvbHZpw7MgbcOhcyBmw6FjaWwgaGFjZXIgdHJhbnNmZXJlbmNpYXMgZWxlY3Ryw7NuaWNhcyB5IHBvciBsbyB0YW50byBjb250YWJpbGl6YXJsbyBlbiBsYSBiYWxhbnphIGRlIHBhZ29zLgotIEVsIGNyZWNpbWllbnRvIHB1ZWRlIHNlciB0YW1iacOpbiBwb3IgbGEgc29saWRhcmlkYWQgZGUgbG9zIG1pZ3JhbnRlcy4KCj5FbiBlbCAyMDAxLCBlbiByZXNwdWVzdGEgYSBsYSAiU29jaWVkYWQgcGFyYSBsYSBwcm9zcGVyaWRhZCIgZW50cmUgTcOpeGljbyB5IEVzdGFkb3MgVW5pZG9zLCBlbCBCYW5jbyBkZSBNw6l4aWNvIHkgbG9zIEJhbmNvcyBkZSBsYSBSZXNlcnZhIEZlZGVyYWwgZGUgbG9zIEVzdGFkb3MgVW5pZG9zIGFjb3JkYXJvbiBlc3R1ZGlhciBsYSBwb3NpYmlsaWRhZCBkZSBpbnRlcmNvbmVjdGFyIHN1cyBzaXN0ZW1hcyBkZSBwYWdvcy4gTGEgaW50ZXJjb25leGnDs24gaGEgcHJvdmlzdG8gYSBudWVzdHJhcyBlY29ub23DrWFzIGRlIHVuIG1lY2FuaXNtbyBlZmljaWVudGUgcGFyYSBpbnRlcmNhbWJpYXIgcGFnb3MgZW50cmUgY3VlbnRhcyBiYW5jYXJpYXMgZGUgYW1ib3MgcGHDrXNlcy4KCj5FbiBvY3R1YnJlIGRlIDIwMDMsIGxvcyBCYW5jb3MgZGUgbGEgUmVzZXJ2YSBGZWRlcmFsIGRlIGxvcyBFc3RhZG9zIFVuaWRvcyB5IGVsIEJhbmNvIGRlIE3DqXhpY28gY29uZWN0YXJvbiBzdXMgc2lzdGVtYXMgZGUgcGFnbyBwYXJhIGVsIGVudsOtbyBkZSBsb3MgcGFnb3MgZGUgbG9zIHBlbnNpb25hZG9zIGRlbCBHb2JpZXJubyBkZSBsb3MgRXN0YWRvcyBVbmlkb3MgcXVlIHJhZGljYW4gZW4gTcOpeGljby4KCj5Qb3N0ZXJpb3JtZW50ZSwgZGVzZGUgZWwgMiBkZSBmZWJyZXJvIGRlIDIwMDQsIGxvcyB1c3VhcmlvcyBkZSBsYXMgaW5zdGl0dWNpb25lcyBmaW5hbmNpZXJhcyBkZSBsb3MgRXN0YWRvcyBVbmlkb3Mgc3VzY3JpdGFzIGEgRGlyZWN0byBhIE3DqXhpY28gcHVlZGVuIGVudmlhciBwYWdvcyBhIGN1YWxxdWllciBjdWVudGEgYmFuY2FyaWEgZW4gTcOpeGljby4KCj5EZXNkZSBqdWxpbyBkZSAyMDA1LCBlc3RlIHNlcnZpY2lvIGRlIHBhZ29zIHNlIHJlZ2lzdHLDsyBjb24gZWwgbm9tYnJlIERpcmVjdG8gYSBNw6l4aWNvCgpFbnRvbmNlcyBwYXJhIGNvbnNpZGVyYXIgY29tbyBwZXJpb2RvcyBxdWUgaGFuIGFmZWN0YWRvIGxhIHNlcmllIGRlIHRpZW1wbyB0ZW5lbW9zOgoKLSAyMDAzLTEwIGZhY2lsaWRhZCBkZSB0cmFuc2ZlcmVuY2lhcyBlbGVjdHLDs25pY2FzCi0gMjAwNy0xMiwgMjAwOS0wNiByZWNlc2nDs24gZ2xvYmFsIHBvciBjcmlzaXMgaGlwb3RlY2FyaWEKLSAyMDIwLTAyLCAyMDIwLTA0IHJlY2VzacOzbiBnbG9iYWwgcG9yIENPVklELTE5Ci0gQXBhcnRpciBkZWwgMjAxOCBoYXkgdW4gY2FtYmlvIGRlIHRlbmRlbmNpYSB5IGVsIGNyZWNpbWlldG8gZXMgYWNlbGVyYWRvLgoKQ29uIGxvcyBncsOhZmljb3MgZGUgcmV6YWdvcyBwb2RlbW9zIGFwcmVjaWFyIHF1ZSBtdWVzdHJhIG1heW9yIGNvcnJlbGFjacOzbiBjb24gZWwgcGVyaW9kbyBpbm1lZGlhdG8gYW50ZXJpb3IgKDEpIHkgZWwgbWlzbW8gcGVyaW9kbyBkZWwgYcOxbyBwYXNhZG8gKDEyKS4gRXMgZGVjaXIsIHNlIGVzcGVyYSBxdWUgc2UgZW52acOpIHVuYSBzaW1pbGFyIGNhbnRpZGFkIGRlIGRpbmVybyBjb21wYXJhZGEgYSBlc3RvcyBkb3MgcGVyaW9kb3MgZGVsIHBhc2FkbyAoMSB5IDEyKSwgcGVybyBwYXJhIGVsIHBlcmlvZG8gMTIgc2UgZXNwZXJhIHF1ZSBzZSBlbnZpw6kgbcOhcyBkaW5lcm8uCgojIyBFc3RhZMOtc3RpY2EgZGVzY3JpcHRpdmEKIyMjIE1lZGlkYXMgZGUgdGVuZGVuY2lhIGNlbnRyYWwKCkNhbGN1bGEgbGEgbWVkaWEsIG1vZGEgeSBtZWRpYW5hLiBFc3RvcyBlc3RhZGlzdGljb3MgcHVlZGVuIHNlciBkZSBsYSB0b3RhbGlkYWQgZGUgbGEgc2VyaWUgbyBwb3IgYcOxbyBvIHBvciBwZXJpb2RvIGVzdGFjaW9uYWwuCgpgYGB7cn0KcHJpbnQocGFzdGUoJ2ZlY2hhIGluaWNpYWwnLCBtaW4oZGF0YSRkYXRlKSkpCnByaW50KHBhc3RlKCdmZWNoYSBmaW5hbCcsIG1heChkYXRhJGRhdGUpKSkKcHJpbnQocGFzdGUoJ29ic2VydmFjaW9uZXMnLCBucm93KGRhdGEpKSkKcHJpbnQocGFzdGUoJ2V4aXN0ZW4nLCBzdW0oaXMubmEoZGF0YSkpLCAnZGF0b3MgZmFsdGFudGVzJykpCmBgYAoKYGBge3J9CnN1bW1hcnkoZGF0YVssICd2YWx1ZSddKQpgYGAKCk9ic2VydmFtb3MgcXVlLCBwb3IgbWVzLCBlbCBwcm9tZWRpbyBkZSBtaWxsb25lcyBkZSBkw7NsYXJlcyBlcyBkZSAkMSw5OTMuMiBtaWxsb25lcyBkZSBkw7NsYXJlcywgZWwgbcOtbmltbyBmdWUgZGUgJDI0OC4xIG1pbGxvbmVzIGRlIGTDs2xhcmVzLCBtaWVudHJhcyBxdWUgZWwgbcOheGltbyBmdWUgZGUgJDUsODE3LjggbWlsbG9uZXMuCgpgYGB7cn0KYm94cGxvdCA9IGRhdGEgJT4lIAogICAgICAgICAgICBtdXRhdGUoeWVhciA9IHllYXIoZGF0ZSkpICU+JSAKICAgICAgICAgICAgZ2dwbG90KGFlcyh4ID0gYXMuZmFjdG9yKHllYXIpLCB5ID0gdmFsdWUpKSArIAogICAgICAgICAgICBnZW9tX2JveHBsb3QoKSArIAogICAgICAgICAgICB4bGFiKCdBw7FvJykgKyAKICAgICAgICAgICAgeWxhYignUmVtZXNhcycpCgpnZ3Bsb3RseShib3hwbG90KQpgYGAKCiMjIyBNZWRpZGFzIGRlIGRpc3BlcnNpw7NuCgpFc3RvcyBlc3RhZMOtc3RpY29zIHF1ZSBub3MgZGFuIGluZm9ybWFjacOzbiBhbCByZXNwZWN0byBkZSBsYSB2YXJpYWJpbGlkYWQgbyBzZXBhcmFjacOzbiBkZSBsb3MgZGF0b3MgZ2VuZXJhbG1lbnRlIHJlc3BlY3RvIGEgbGEgbWVkaWEuIE5vcyBheXVkYW4gYSBjb21wcmVuZGVyIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRhdG9zIHkgZXZpdGFuIHRvbWFyIGNvbmNsdXNpb25lcyBlcnLDs25lYXMgYWwgY29tcGFyYXIgZGlzdGludG9zIGdydXBvcy4KCmBgYHtyfQpzZChkYXRhJHZhbHVlKQpgYGAKCmBgYHtyfQp2YXIoZGF0YSR2YWx1ZSkKYGBgCgpgYGB7cn0KbGlicmFyeShFbnZTdGF0cykKa3VydG9zaXMoZGF0YSR2YWx1ZSkKc2tld25lc3MoZGF0YSR2YWx1ZSkKc2hhcGlyby50ZXN0KGRhdGEkdmFsdWUpCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2dFeHRyYSkKcCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHg9ZGF0ZSwgeT12YWx1ZSkpICsgCiAgICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0xMDAwKSArIAogICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9MzAwMCkgKwogICAgICAgIGdlb21fcG9pbnQoKSArIAogICAgICAgIGdndGl0bGUoJ1JlbWVzYXMgcG9yIG1lcycpICsgeWxhYignTWlsbG9uZXMgZGUgZMOzbGFyZXMnKSArIHhsYWIoJ0ZlY2hhJykKCmdnTWFyZ2luYWwocCwgdHlwZT0naGlzdG9ncmFtJywgbWFyZ2lucyA9ICd5JykKYGBgCgpgYGB7cn0KaGlzdG9ncmFtID0gZ2dwbG90KGRhdGEsIGFlcyh4ID0gdmFsdWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oIGJpbnMgPSAyMCwgZmlsbCA9ICJibGFjayIsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbWEiLAogICAgICAgeCA9ICJWYWx1ZSIsCiAgICAgICB5ID0gIkRlbnNpZGFkIikKCmdncGxvdGx5KGhpc3RvZ3JhbSkKYGBgCgpMYSBkaXN0cmlidWNpw7NuIHByZXNlbnRhIHVuIHNlc2dvIGRlIHNpbWV0csOtYSBuZWdhdGl2byBhIGxhIGl6cXVpZXJkYSB5IGF1bnF1ZSBsb3MgdmFsb3JlcyBubyBzb24gdGFuIGdyYW5kZXMsIGFsZ3VuYSB0cmFuc2Zvcm1hY2nDs24gc2Vyw61hIMO6dGlsIGFudGVzIGRlIGhhY2VyIGxhIGRlc2NvbXBvc2ljacOzbiBkZSBsYSBzZXJpZSB5IGxvcyBwcm9uw7NzdGljb3MuCgojIyMgVmFsb3JlcyBhdMOtcGljb3MKCkxhIGRldGVjY2nDs24gZGUgb3V0bGllcnMgZXMgaW1wb3J0YW50ZSBwYXJhIGFmaW5hciBudWVzdHJvIHByb27Ds3N0aWNvIHkgZWxpbWluYXIgbGFzIG9ic2VydmFjaW9uZXMgYXTDrXBpY2FzLgpFeGlzdGVuIGRpZmVyZW50ZXMgZm9ybWFzIGRlIGRlZmluaXIgdmFsb3JlcyBhdMOtcGljb3MuIEVuIGVzdGUgY2Fzbywgc2kgbG9zIG91dGxpZXJzIHNvbiAxLjUgdmVjZXMgZWwgcmFuZ28gaW50ZXJjdWFydMOtbGljbyBwb3IgZW5jaW1hIHkgZGViYWpvIGRlbCAxIHkgMyBjdWFydGlsLCBzw60gaGF5IHZhbG9yZXMgYXTDrXBpY29zLgoKYGBge3J9CnR0bF9tX2RscnMgPC0gZGF0YSAlPiUgc2VsZWN0KCd2YWx1ZScpCnR0bF9tX2RscnMgPC0gYXMubnVtZXJpYyh1bmxpc3QodHRsX21fZGxyc1ssMV0pKQpzdW1tYXJ5KHR0bF9tX2RscnMpWzJdIC0gMS41KklRUih0dGxfbV9kbHJzKSA+PSBzdW1tYXJ5KHR0bF9tX2RscnMpWzFdCnN1bW1hcnkodHRsX21fZGxycylbNV0gKyAxLjUqSVFSKHR0bF9tX2RscnMpIDw9IHN1bW1hcnkodHRsX21fZGxycylbNl0KYGBgCgpgYGB7cn0Kc3VtbWFyeSh0dGxfbV9kbHJzKVsyXSAtIDMqSVFSKHR0bF9tX2RscnMpID49IHN1bW1hcnkodHRsX21fZGxycylbMV0Kc3VtbWFyeSh0dGxfbV9kbHJzKVs1XSArIDMqSVFSKHR0bF9tX2RscnMpIDw9IHN1bW1hcnkodHRsX21fZGxycylbNl0KYGBgCgoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCnAgPC0gZGF0YSAlPiUgYXNfdGliYmxlICU+JSBncm91cF9ieSh5ZWFycz15ZWFyKGRhdGUpKSAlPiUKICAgIHN1bW1hcmlzZShyZW1lc2FzPXN1bSh2YWx1ZSkpICU+JQogICAgYXJyYW5nZShkZXNjKHllYXJzKSklPiUKICAgIG11dGF0ZShjaGFuZ2UgPSAocmVtZXNhcy9sZWFkKHJlbWVzYXMpIC0gMSkgKiAxMDApICU+JSAKICAgIGZpbHRlcih5ZWFycyA+IDE5OTUpICU+JSAKICAgIGZpbHRlcih5ZWFycyA8IDIwMjMpCgptZWFuX2dyb3d0aCA8LSBkYXRhICU+JSBhc190aWJibGUgJT4lIGdyb3VwX2J5KHllYXJzPXllYXIoZGF0ZSkpICU+JQogICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShyZW1lc2FzPXN1bSh2YWx1ZSkpICU+JQogICAgICAgICAgICAgICAgICAgIGFycmFuZ2UoZGVzYyh5ZWFycykpJT4lCiAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGNoYW5nZSA9IChyZW1lc2FzL2xlYWQocmVtZXNhcykgLSAxKSAqIDEwMCkgJT4lIAogICAgICAgICAgICAgICAgICAgIGZpbHRlcih5ZWFycyA+IDE5OTUpICU+JSAKICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoeWVhcnMgPCAyMDIyKSAlPiUKICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UobWVhbihjaGFuZ2UpKQoKbWVhbl9ncm93dGggPC0gbWVhbl9ncm93dGgkYG1lYW4oY2hhbmdlKWAKCmdncGxvdChwLCBhZXMoeD15ZWFycywgeT1jaGFuZ2UpKSArCiAgICBnZW9tX2xpbmUoKSArCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9bWVhbl9ncm93dGgpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdD0wKSArCiAgICBnZ3RpdGxlKCdDYW1iaW8gcG9yY2VudHVhbCBwb3IgYcOxbycpICsgeWxhYignJScpICsgeGxhYignTWVzJykKYGBgCkVsIGNyZWNpbWllbnRvIHByb21lZGlvIGVzIGRlIDExLjQ4JS4KCiMgNCkgUHJvbsOzc3RpY29zIGJhc2UKCiMjIERlZmluZSBsb3MgcGVyaW9kb3MgZGUgcHJ1ZWJhIHkgZW50cmVuYW1pZW50bwoKRGVwZW5kaWVuZG8gZGUgbGEgY2FudGlkYWQgZGUgZGF0b3MgeSBsYSBwZXJpb2RpY2lkYWQgcG9kcsOtYXMgZGVmaW5pciBkaWZlcmVudGUgY2FudGlkYWQgZGUgb2JzZXJ2YWNpb25lcy4gTGEgcmVnbGEgZGUgcHVsZ2FyIGVzIHVzYXIgODAlIGRlIGxvcyBkYXRvcyBwYXJhIGVudHJlbmFyIHkgZWwgcmVzdGFudGUgMjAlIHBhcmEgdmFsaWRhciBsb3MgcmVzdWx0YWRvcy4KClBhcmEgZXN0YSBzZXJpZSBkZSB0aWVtcG8gNiBtZXNlcyBkZSB2YWxpZGFjacOzbiBzb24gc3VmaWNpZW50ZXMuCgpUYW1iacOpbiBlbiBlbCBsaWJybyBbRm9yZWNhc3Q6IFByaW5jaXBsZXMgYW5kIFByYWN0aWNlXShodHRwczovL290ZXh0cy5jb20vZnBwMy90b29sYm94Lmh0bWwpIGNhcMOtdHVsbyA1CgoKYGBge3J9CnRyYWluIDwtIGRhdGEgJT4lIHNlbGVjdCh2YWx1ZSkgJT4lIGZpbHRlcl9pbmRleCgiMTk5NSBKYW4iIH4gIjIwMjMgSnVuIikKdGVzdCA8LSBkYXRhICU+JSBzZWxlY3QodmFsdWUpICU+JSBmaWx0ZXJfaW5kZXgoIjIwMjMgSnVuIiB+ICIyMDIzIERlYyIpCnRzdG5nX3ByZHMgPC0gNgpmcmNzdF9wcmRzIDwtIDYKYGBgCgojIyBTZWFzb25hbCBOYWl2ZQoKRW4gZWwgbGlicm8gW0ZvcmVjYXN0OiBQcmluY2lwbGVzIGFuZCBQcmFjdGljZV0oaHR0cHM6Ly9vdGV4dHMuY29tL2ZwcDMvanVkZ21lbnRhbC5odG1sKSBjYXDDrXR1bG8gNSwgeSBub3RlYm9vayBkZSBjbGFzZSBbcHJvbsOzc3RpY29zIGJhc2VdKGh0dHBzOi8vaXRlc28uaW5zdHJ1Y3R1cmUuY29tL2NvdXJzZXMvMzY2NzMvZmlsZXMvNzEzMDQ3MT9tb2R1bGVfaXRlbV9pZD0xNTMzNzkyJmZkX2Nvb2tpZV9zZXQ9MSkgc2UgbXVlc3RyYW4gZGlmZXJlbnRlcyBtw6l0b2RvcyBpbmljaWFsZXMgcGFyYSBoYWNlciBlc3RpbWFjaW9uZXMuIEVzdG9zIG3DqXRvZG9zIGluaWNpYWxlcyBzb24gbGlnYWRvcyBhIGxhIGV4cGVyaWVuY2lhIGVuIGxhIHNlcmllIHkgZWwgYW7DoWxpc2lzIGV4cGxvcmF0b3JpbyByZWFsaXphZG8gY29uIGFudGVyaW9yaWRhZC4KClV0aWxpemFuZG8gbGEgZnVuY2nDs25gIGZhYmxlOjpTTkFJVkVgIHBhcmEgZWwgcHJpbWVyIHByb27Ds3N0aWNvIGJhc2UKCmBgYHtyfQpsaWJyYXJ5KGZhYmxlKQptb2RlbHNfZml0IDwtIHRyYWluICU+JSAKICAgIG1vZGVsKGBTZWFzb25hbCBuYWl2ZWAgPSBTTkFJVkUodmFsdWUpKQptb2RlbHNfdHN0IDwtIG1vZGVsc19maXQgJT4lIGZvcmVjYXN0KGggPSB0c3RuZ19wcmRzKQptYXBlX3NuIDwtIChtb2RlbHNfZml0ICU+JSBmb3JlY2FzdChoID0gdHN0bmdfcHJkcykgJT4lIGFjY3VyYWN5KHRlc3QpKSRNQVBFCnNuYWl2ZV9wbG90IDwtIG1vZGVsc190c3QgJT4lIGF1dG9wbG90KGZpbHRlcl9pbmRleChkYXRhLCAiMjAxOCBKYW4iIH4gLikpICsKICAgIGdndGl0bGUoJ1NlYXNvbmFsIE5haXZlJykgKyB5bGFiKCdSZW1lc2FzJykgKyB4bGFiKCdNZXMnKQoKc25haXZlX3Bsb3QKYGBgCgoKIyA1KSBEZXNjb21wb3NpY2nDs24KCiMjIFRyYW5zZm9ybWFjaW9uZXMgeSBhZGp1c3RlcwoKQ29uc3VsdGEgZWwgbGlicm8gW0ZvcmVjYXN0OiBQcmluY2lwbGVzIGFuZCBQcmFjdGljZV0oaHR0cHM6Ly9vdGV4dHMuY29tL2ZwcDMvdHJhbnNmb3JtYXRpb25zLmh0bWwpIGNhcMOtdHVsbyAzLjEKCkFqdXN0YXIgbG9zIGRhdG9zIGhpc3TDs3JpY29zIGEgbWVudWRvIHB1ZWRlIGNvbmR1Y2lyIGEgc2VyaWVzIHRlbXBvcmFsZXMgbcOhcyBzaW1wbGVzLiBlamVtcGxvcyBkZSBwdWVkZW4gc2VyIGFqdXN0ZXMgZGUgY2FsZW5kYXJpbywgYWp1c3RlcyBkZSBwb2JsYWNpw7NuLCBhanVzdGVzIGRlIGluZmxhY2nDs24geSB0cmFuc2Zvcm1hY2lvbmVzIG1hdGVtw6F0aWNhcy4gRWwgcHJvcMOzc2l0byBkZSBlc3RvcyBhanVzdGVzIHkgdHJhbnNmb3JtYWNpb25lcyBlcyBzaW1wbGlmaWNhciBsb3MgcGF0cm9uZXMgZW4gbG9zIGRhdG9zIGhpc3TDs3JpY29zIGVsaW1pbmFuZG8gZnVlbnRlcyBjb25vY2lkYXMgZGUgdmFyaWFjacOzbiBvIGhhY2llbmRvIHF1ZSBlbCBwYXRyw7NuIHNlYSBtw6FzIGNvbnNpc3RlbnRlIGVuIHRvZG8gZWwgY29uanVudG8gZGUgZGF0b3MuIExvcyBwYXRyb25lcyBtw6FzIHNpbXBsZXMgc3VlbGVuIHNlciBtw6FzIGbDoWNpbGVzIGRlIG1vZGVsYXIgeSBjb25kdWNlbiBhIHByb27Ds3N0aWNvcyBtw6FzIHByZWNpc29zLgoKQ8OzbW8geWEgc2UgbWVuY2lvbsOzIGFudGVyaW9ybWVudGUgY29uIGVsIGhpc3RvZ3JhbWEsIHkgY29uIG9ic2VydmFyIGxhcyBtYWduaXR1ZGVzIGRlIGxvcyB2YWxvcmVzIGFsIGluaWNpbyB5IGZpbmFsIGRlIGxhIHNlcmllIGVzIGNvbnZlbmllbnRlIHVuYSB0cmFuc2Zvcm1hY2nDs24gZGUgcG90ZW5jaWEuIEVsIGhpc3RvZ3JhbWEgeSBlbCBzZXNnbyB0YW1iacOpbiBtdWVzdHJhIHNlc2dvIG5lZ2F0aXZvLiBBZGVtw6FzLCBsYSBwcnVlYmEgZGUgbm9ybWFsaWRhZCBTSEFQSVJPLVdJTEsgKGFscGhhID0gMC4wNSkKCgpgYGB7cn0KcXFub3JtKGRhdGEkdmFsdWUpCnFxbGluZShkYXRhJHZhbHVlKQpgYGAKClZhbG9yIHAgZXMgbWVub3IgcXVlIEFscGhhIGVudG9uY2VzIG5vIHRlbmVtb3MgdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLiBEZSBoZWNobywgZXN0YW1vcyBsZWpvcyBkZSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwgcGVybyBlbCBzZXNnbyBubyBlc3RhIHRhbiBtYWwgc2llbmRvIDAuNS4gUXVlcmVtb3MgbG8gbcOhcyBhY2VyY2FkbyBhIDAgZGUgc2VzZ28uCgpBdW5xdWUgc2UgcHVlZGUgZW50ZW5kZXIgeSB1c2FyIGxhIHRyYW5zZm9ybWFjacOzbiBib3ggY294IHBhcmEgdHJhbnNmb3JtYXIgdW5hIGRpc3RyaWJ1Y2nDs24gbm8gbm9ybWFsIGEgdW5hIG5vcm1hbCwgZWwgcHJpbmNpcGFsIG9iamV0aXZvIGVzIGNvcnJlZ2lyIHNlc2dvcyB5IHZhcmlhbnphcyBkZXNpZ3VhbGVzIGRlIGxhIHNpZ3VpZW50ZSBtYW5lcmE6CgokJAp5KFxsYW1iZGEpID1cYmVnaW57Y2FzZXN9CiAgICBcZnJhY3soeV5cbGFtYmRhIC0gMSl9e1xsYW1iZGF9JiBcbGFtYmRhIFxuZXEgMCAsXFwKICAgIGxvZyh5KSYgICBcbGFtYmRhID0gMC4KICAgIFxlbmR7Y2FzZXN9CiQkCgpFbCBsYW1iZGEgw7NwdGltbyBzZSBlbmN1ZW50cmEgY3VhbmRvIHNlIGVuY3VlbnRyYSBsYSBkaXN0cmlidWNpw7NuIGNvbiBlbCBtw6F4aW1vIGxvZ2xpa2VsaWhvb2QgbyBjb24gZWwgY29lZmljaWVudGUgZGVsIGdyw6FmaWNvIGRlIHByb2JhYmlsaWRhZCBkZSBjb3JyZWxhY2nDs24gbyBTaGFwaXJvLVdpbGsuCgo+IEJpY2tlbCwgUC4gSi4sICYgRG9rc3VtLCBLLiBBLiAoMTk4MSkuIEFuIGFuYWx5c2lzIG9mIHRyYW5zZm9ybWF0aW9ucyByZXZpc2l0ZWQuIEpvdXJuYWwgb2YgdGhlIEFtZXJpY2FuIFN0YXRpc3RpY2FsIEFzc29jaWF0aW9uLCA3NigzNzQpLCAyOTbigJMzMTEuIFtET0ldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMDgwLzAxNjIxNDU5LjE5ODEuMTA0Nzc2NDkpCj4gCj4gQm94LCBHLiBFLiBQLiwgJiBDb3gsIEQuIFIuICgxOTY0KS4gQW4gYW5hbHlzaXMgb2YgdHJhbnNmb3JtYXRpb25zLiBKb3VybmFsIG9mIHRoZSBSb3lhbCBTdGF0aXN0aWNhbCBTb2NpZXR5LiBTZXJpZXMgQiwgU3RhdGlzdGljYWwgTWV0aG9kb2xvZ3ksIDI2KDIpLCAyMTHigJMyNTIuIFtET0ldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMTExL2ouMjUxNy02MTYxLjE5NjQudGIwMDU1My54KQoKCmBgYHtyfQpiYyA8LSBFbnZTdGF0czo6Ym94Y294KGRhdGEkdmFsdWUsIGxhbWJkYT1jKC0yLCAyKSwgb3B0aW1pemU9VFJVRSwgb2JqZWN0aXZlLm5hbWU9J0xvZy1MaWtlbGlob29kJykKYmNfZGF0YSA8LSBFbnZTdGF0czo6Ym94Y294VHJhbnNmb3JtKGRhdGEkdmFsdWUsIGJjJGxhbWJkYSkKCnNrZXduZXNzKGJjX2RhdGEpCnNoYXBpcm8udGVzdChiY19kYXRhKQpxcW5vcm0oYmNfZGF0YSkKcXFsaW5lKGJjX2RhdGEpCgpkYXRhIDwtIGRhdGEgJT4lIG11dGF0ZSgncmVtZXNhc190cm4nID0gYmNfZGF0YSkKYGBgCgojIyBDb21wb25lbnRlcyB5IGRlc2NvbXBvc2ljacOzbiBTVEwKCkNvbnN1bHRhIGVsIGxpYnJvIFtGb3JlY2FzdDogUHJpbmNpcGxlcyBhbmQgUHJhY3RpY2VdKGh0dHBzOi8vb3RleHRzLmNvbS9mcHAzL3RyYW5zZm9ybWF0aW9ucy5odG1sKSBjYXDDrXR1bG8gMy42CgpQYXJhIGVzdHVkaWFyIGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlIHRlbmRlbmNpYSB5IGVzdGFjaW9uYWxpZGFkIHNlIGRlc2NvbXBvbmUgeSBncmFmaWNhciB1c2FuZG8gZWwgbcOpdG9kbyBTVEwuCkxhIGZ1bmNpw7NuIHBlciBkZSAqcGVyaW9kaWNpdHkqIGVzIGxhIG3DoXMgYWRlY3VhZGEgYWwgcGFyw6FtZXRybyBkZSBzdWF2aXphY2nDs24gZXN0YWNpb25hbCAqcy53aW5kb3dzKi4gRXMgZWwgY29tcG9uZW50ZSBlc3RhY2lvbmFsIGVzIGVsIG3DoXMgcGVxdWXDsW8sIHNpZW5kbyBsYSB0ZW5kZW5jaWEgbcOhcyBzaWduaWZpY2F0aXZhLgoKUG9kZW1vcyBvYnNlcnZhciBlbiBlbCBjb21wb25lbnRlIGVzdGFjaW9uYWwgY2FwdHVyYSwgcXVlIGVsIGluaWNpbyBkZSBhw7FvIGVzIGVsIG3DoXMgZmxvaml0byB5IHF1ZSwgYSBtZWRpYWRvcyBkZWwgYcOxbyBlcyBjdWFuZG8gc2UgZW52w61hbiBtw6FzIHJlbWVzYXMuCgpFbCBjb21wZXRlbnRlIGRlIHRlbmRlbmNpYSB5IHJlbWFuZW50ZXMgb2JzZXJ2YW1vcyB5IGNvbmZpcm1hbW9zIGxvIG1lbmNpb25hZG8gYW50ZXJpb3JtZW50ZS4gQSBwYXJ0aXIgZGVsIDIwMDQgZWwgZW52w61vIGRlIHJlbWVzYXMsIG8gZWwgcmVnaXN0cm8sIGF1bWVudGEgY29uc2lkZXJhYmxlbWVudGUgeSBlbCBlbiAyMDA4IHkgMjAyMCBlbCByZW1hbmVudGUgZXMgbXV5IHNpZ25pZmljYXRpdm8uIFRhbWJpw6luLCBhIHBhcnRpciBkZWwgMjAyMCBlbCBjb21wb25lbnRlIHJlbWFuZW50ZSBzZSBhY2VudMO6YS4KCiFbXSguL2ltYWdlcy9zdGwucG5nKQoKPiBDbGV2ZWxhbmQsIFIuIEIuLCBDbGV2ZWxhbmQsIFcuIFMuLCBNY1JhZSwgSi4gRS4sICYgVGVycGVubmluZywgSS4gSi4gKDE5OTApLiBTVEw6IEEgc2Vhc29uYWwtdHJlbmQgZGVjb21wb3NpdGlvbiBwcm9jZWR1cmUgYmFzZWQgb24gbG9lc3MuIEpvdXJuYWwgb2YgT2ZmaWNpYWwgU3RhdGlzdGljcywgNigxKSwgM+KAkzMzLiBbaHR0cDovL2JpdC5seS9zdGwxOTkwXShodHRwOi8vYml0Lmx5L3N0bDE5OTApCgpgYGB7cn0Kc3RsX21vZGVsID0gZGF0YSAlPiUgZHBseXI6OnNlbGVjdChyZW1lc2FzX3RybikgJT4lIHN0bChzLndpbmRvdyA9ICdwZXInKQpwbG90KHN0bF9tb2RlbCxtYWluID0gJ0Rlc2NvbXBvc2ljw7NuIGRlIGxhIHNlcmllIGNvbiBTVEwnKQpgYGAKCiMgNikgUHJvbsOzc3RpY29zIGJhc2UKCiMjIERlZmluZSBsb3MgcGVyaW9kb3MgZGUgcHJ1ZWJhIHkgZW50cmVuYW1pZW50bwoKRGVwZW5kaWVuZG8gZGUgbGEgY2FudGlkYWQgZGUgZGF0b3MgeSBsYSBwZXJpb2RpY2lkYWQgcG9kcsOtYXMgZGVmaW5pciBkaWZlcmVudGUgY2FudGlkYWQgZGUgb2JzZXJ2YWNpb25lcy4gTGEgcmVnbGEgZGUgcHVsZ2FyIGVzIHVzYXIgODAlIGRlIGxvcyBkYXRvcyBwYXJhIGVudHJlbmFyIHkgZWwgcmVzdGFudGUgMjAlIHBhcmEgdmFsaWRhciBsb3MgcmVzdWx0YWRvcy4KClBhcmEgZXN0YSBzZXJpZSBkZSB0aWVtcG8gNiBtZXNlcyBkZSB2YWxpZGFjacOzbiBzb24gc3VmaWNpZW50ZXMuCgpUYW1iacOpbiBlbiBlbCBsaWJybyBbRm9yZWNhc3Q6IFByaW5jaXBsZXMgYW5kIFByYWN0aWNlXShodHRwczovL290ZXh0cy5jb20vZnBwMy90b29sYm94Lmh0bWwpIGNhcMOtdHVsbyA1CgoKYGBge3J9CnRyYWluIDwtIGRhdGEgJT4lIHNlbGVjdChyZW1lc2FzX3RybikgJT4lIGZpbHRlcl9pbmRleCgiMTk5NSBKYW4iIH4gIjIwMjMgSnVuIikKdGVzdCA8LSBkYXRhICU+JSBzZWxlY3QocmVtZXNhc190cm4pICU+JSBmaWx0ZXJfaW5kZXgoIjIwMjMgSnVuIiB+ICIyMDIzIERlYyIpCnRzdG5nX3ByZHMgPC0gNgpmcmNzdF9wcmRzIDwtIDYKYGBgCgojIyBTZWFzb25hbCBOYWl2ZQoKRW4gZWwgbGlicm8gW0ZvcmVjYXN0OiBQcmluY2lwbGVzIGFuZCBQcmFjdGljZV0oaHR0cHM6Ly9vdGV4dHMuY29tL2ZwcDMvanVkZ21lbnRhbC5odG1sKSBjYXDDrXR1bG8gNSwgeSBub3RlYm9vayBkZSBjbGFzZSBbcHJvbsOzc3RpY29zIGJhc2VdKGh0dHBzOi8vaXRlc28uaW5zdHJ1Y3R1cmUuY29tL2NvdXJzZXMvMzY2NzMvZmlsZXMvNzEzMDQ3MT9tb2R1bGVfaXRlbV9pZD0xNTMzNzkyJmZkX2Nvb2tpZV9zZXQ9MSkgc2UgbXVlc3RyYW4gZGlmZXJlbnRlcyBtw6l0b2RvcyBpbmljaWFsZXMgcGFyYSBoYWNlciBlc3RpbWFjaW9uZXMuIEVzdG9zIG3DqXRvZG9zIGluaWNpYWxlcyBzb24gbGlnYWRvcyBhIGxhIGV4cGVyaWVuY2lhIGVuIGxhIHNlcmllIHkgZWwgYW7DoWxpc2lzIGV4cGxvcmF0b3JpbyByZWFsaXphZG8gY29uIGFudGVyaW9yaWRhZC4KClV0aWxpemFuZG8gbGEgZnVuY2nDs25gIGZhYmxlOjpTTkFJVkVgIHBhcmEgZWwgcHJpbWVyIHByb27Ds3N0aWNvIGJhc2UKCmBgYHtyfQpsaWJyYXJ5KGZhYmxlKQptb2RlbHNfZml0IDwtIHRyYWluICU+JSAKICAgIG1vZGVsKGBTZWFzb25hbCBuYWl2ZWAgPSBTTkFJVkUocmVtZXNhc190cm4pKQptb2RlbHNfdHN0IDwtIG1vZGVsc19maXQgJT4lIGZvcmVjYXN0KGggPSB0c3RuZ19wcmRzKQptYXBlX3NuIDwtIChtb2RlbHNfZml0ICU+JSBmb3JlY2FzdChoID0gdHN0bmdfcHJkcykgJT4lIGFjY3VyYWN5KHRlc3QpKSRNQVBFCnNuYWl2ZV9wbG90IDwtIG1vZGVsc190c3QgJT4lIGF1dG9wbG90KGZpbHRlcl9pbmRleChkYXRhLCAiMjAxOCBKYW4iIH4gLikpICsKICAgIGdndGl0bGUoJ1NlYXNvbmFsIE5haXZlJykgKyB5bGFiKCdSZW1lc2FzJykgKyB4bGFiKCdNZXMnKQoKc25haXZlX3Bsb3QKYGBgCgo=